Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(multi-select): render checkboxes for form data #1835

Merged
merged 3 commits into from
Oct 27, 2023

Conversation

theetrain
Copy link
Collaborator

@theetrain theetrain commented Oct 26, 2023

Fixes #1742

MultiSelect up til now wasn't rendering hidden inputs in order to be submittable within a <form>. With this enhancement:

  1. MultiSelect renders all items as <input type="hidden" name="some-id" value="true" /> using value="true" for checked items and value="false" for unchecked items by default.
  2. New prop selectedOnly only renders hidden inputs for user-selected items.
  3. New prop combineValues renders a single hidden input with comma-separated values, or using a consumer-provided delimiter.
  4. Prop itemToInput is enhanced to perform double duty for user-visible checkboxes as well as the hidden inputs, mainly to help override name and value attributes among the hidden inputs.
  5. Use CSS to show and hide MultiSelect values so that their checkboxes are form-submittable

Feature (3) was a personal need in order to submit an array of values within a form, but I felt the default behaviour should be checkbox-like as per point (1) assuming that's what consumers of MultiSelect would expect.

See included documentation for more examples.

The MultiSelect wasn't rendering form-submittable inputs. This fix adds two new props to help customize how the hidden inputs render.

See #1742
@theetrain theetrain requested a review from metonym October 26, 2023 02:09
* Override the item name, title, labelText passed to the checkbox input
* @type {(item: MultiSelectItem) => { name?: string; labelText?: any; title?: string; }}
* Override the item name, title, labelText, or value passed to the user-selectable checkbox input as well as the hidden inputs.
* @type {(item: MultiSelectItem) => { name?: string; labelText?: any; title?:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: I think JSDoc parses this fine, but in my VSCode IDE the parsed @type is formatted strangely.

Suggested change
* @type {(item: MultiSelectItem) => { name?: string; labelText?: any; title?:
* @type {(item: MultiSelectItem) => { name?: string; labelText?: any; title?: string; value?: string }}
Screenshot 2023-10-25 at 10 10 12 PM

* Set to `true` to only render selected options as hidden inputs for form submission.
* @type {boolean}
*/
export let selectedOnly = false
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you run Prettier to format this file? I think that the trailing semicolons will be applied.

Copy link
Collaborator

@metonym metonym left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM – elegant fix and update to the docs.

@theetrain
Copy link
Collaborator Author

theetrain commented Oct 26, 2023

Thanks @metonym, though I think I had a new realization: if I conditionally hide the ListBox using display: none CSS, its checkbox inputs will still be included as part of the submitted form data:

Reference:

{#if open}
<ListBoxMenu
aria-label="{ariaLabel}"
id="{id}"
aria-multiselectable="true"
>

Refactor:

-  {#if open}
+  <div class:hidden="{!open}">
      <ListBoxMenu
        aria-label="{ariaLabel}"
        id="{id}"
        aria-multiselectable="true"
      >
<!-- stuff -->

+<style>
+ .hidden {
+   display: none;
+ }
+</style>

Minimal demo: https://www.sveltelab.dev/ibxj8ki83lee147

This is great for progressive enhancement down the road, once the popover API becomes stable. With that said, should I refactor to use the above logic? I can probably remove the new props as well and have my own project make use of the checkboxes; leveraging itemToInput to render custom name attributes for my needs.

What do you think?

@metonym
Copy link
Collaborator

metonym commented Oct 26, 2023

That approach seems valid.

I'll admit that for one-line style changes, I have a slight preference for using the style: directive.

@theetrain theetrain merged commit 7ba52df into master Oct 27, 2023
2 checks passed
@theetrain theetrain deleted the fix/1742-multiselect-form branch October 27, 2023 01:21
@theetrain theetrain changed the title feat(multi-select): customize hidden inputs fix(multi-select): render checkboxes for form data Oct 27, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

MultiSelect not submiting payload inside a form
2 participants