chore(multi-select): keep checkboxes rendered in DOM

Display ListBox via CSS
This commit is contained in:
Enrico Sacchetti 2023-10-26 16:53:21 -04:00
commit 43ac7a811f
5 changed files with 44 additions and 133 deletions

View file

@ -2356,7 +2356,7 @@ export interface MultiSelectItem {
### Props ### Props
| Prop name | Required | Kind | Reactive | Type | Default value | Description | | Prop name | Required | Kind | Reactive | Type | Default value | Description |
| :------------------------------ | :------------------------ | :---------------------------------------------------------------------------------------------------------------------------- | :------- | ------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | :----------------------- | :------- | :--------------- | :------- | ---------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| highlightedId | No | <code>let</code> | Yes | <code>null &#124; MultiSelectItemId</code> | <code>null</code> | Id of the highlighted ListBoxMenuItem | | highlightedId | No | <code>let</code> | Yes | <code>null &#124; MultiSelectItemId</code> | <code>null</code> | Id of the highlighted ListBoxMenuItem |
| selectionRef | No | <code>let</code> | Yes | <code>null &#124; HTMLDivElement</code> | <code>null</code> | Obtain a reference to the selection element | | selectionRef | No | <code>let</code> | Yes | <code>null &#124; HTMLDivElement</code> | <code>null</code> | Obtain a reference to the selection element |
| fieldRef | No | <code>let</code> | Yes | <code>null &#124; HTMLDivElement</code> | <code>null</code> | Obtain a reference to the field box element | | fieldRef | No | <code>let</code> | Yes | <code>null &#124; HTMLDivElement</code> | <code>null</code> | Obtain a reference to the field box element |
@ -2367,10 +2367,7 @@ export interface MultiSelectItem {
| selectedIds | No | <code>let</code> | Yes | <code>ReadonlyArray<MultiSelectItemId></code> | <code>[]</code> | Set the selected ids | | selectedIds | No | <code>let</code> | Yes | <code>ReadonlyArray<MultiSelectItemId></code> | <code>[]</code> | Set the selected ids |
| items | No | <code>let</code> | Yes | <code>ReadonlyArray<MultiSelectItem></code> | <code>[]</code> | Set the multiselect items | | items | No | <code>let</code> | Yes | <code>ReadonlyArray<MultiSelectItem></code> | <code>[]</code> | Set the multiselect items |
| itemToString | No | <code>let</code> | No | <code>(item: MultiSelectItem) => any</code> | <code>(item) => item.text &#124;&#124; item.id</code> | Override the display of a multiselect item | | itemToString | No | <code>let</code> | No | <code>(item: MultiSelectItem) => any</code> | <code>(item) => item.text &#124;&#124; item.id</code> | Override the display of a multiselect item |
| itemToInput | No | <code>let</code> | No | <code>(item: MultiSelectItem) => { name?: string; labelText?: any; title?: | | itemToInput | No | <code>let</code> | No | <code>(item: MultiSelectItem) => { name?: string; labelText?: any; title?: string; value?: string }</code> | <code>(item) => {}</code> | Override the item name, title, labelText, or value passed to the user-selectable checkbox input as well as the hidden inputs. |
| string; value?: string }</code> | <code>(item) => {}</code> | Override the item name, title, labelText, or value passed to the user-selectable checkbox input as well as the hidden inputs. |
| selectedOnly | No | <code>let</code> | No | <code>boolean</code> | <code>false</code> | Set to `true` to only render selected options as hidden inputs for form submission. |
| combineValues | No | <code>let</code> | No | <code>false &#124; true &#124; string</code> | <code>false</code> | Combine selected items as comma-separated values when submitted in a form.<br />If set to `true`, the default separator is a comma `,`.<br />Pass in a string to override the separator. |
| size | No | <code>let</code> | No | <code>"sm" &#124; "lg" &#124; "xl"</code> | <code>undefined</code> | Set the size of the combobox | | size | No | <code>let</code> | No | <code>"sm" &#124; "lg" &#124; "xl"</code> | <code>undefined</code> | Set the size of the combobox |
| type | No | <code>let</code> | No | <code>"default" &#124; "inline"</code> | <code>"default"</code> | Specify the type of multiselect | | type | No | <code>let</code> | No | <code>"default" &#124; "inline"</code> | <code>"default"</code> | Specify the type of multiselect |
| direction | No | <code>let</code> | No | <code>"bottom" &#124; "top"</code> | <code>"bottom"</code> | Specify the direction of the multiselect dropdown menu | | direction | No | <code>let</code> | No | <code>"bottom" &#124; "top"</code> | <code>"bottom"</code> | Specify the direction of the multiselect dropdown menu |

View file

@ -7007,7 +7007,7 @@
"name": "itemToInput", "name": "itemToInput",
"kind": "let", "kind": "let",
"description": "Override the item name, title, labelText, or value passed to the user-selectable checkbox input as well as the hidden inputs.", "description": "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?:\nstring; value?: string }", "type": "(item: MultiSelectItem) => { name?: string; labelText?: any; title?: string; value?: string }",
"value": "(item) => {}", "value": "(item) => {}",
"isFunction": true, "isFunction": true,
"isFunctionDeclaration": false, "isFunctionDeclaration": false,
@ -7015,30 +7015,6 @@
"constant": false, "constant": false,
"reactive": false "reactive": false
}, },
{
"name": "selectedOnly",
"kind": "let",
"description": "Set to `true` to only render selected options as hidden inputs for form submission.",
"type": "boolean",
"value": "false",
"isFunction": false,
"isFunctionDeclaration": false,
"isRequired": false,
"constant": false,
"reactive": false
},
{
"name": "combineValues",
"kind": "let",
"description": "Combine selected items as comma-separated values when submitted in a form.\nIf set to `true`, the default separator is a comma `,`.\nPass in a string to override the separator.",
"type": "false | true | string",
"value": "false",
"isFunction": false,
"isFunctionDeclaration": false,
"isRequired": false,
"constant": false,
"reactive": false
},
{ {
"name": "selectedIds", "name": "selectedIds",
"kind": "let", "kind": "let",

View file

@ -14,10 +14,9 @@
By default, items will be ordered alphabetically based on the `item.text` value. By default, items will be ordered alphabetically based on the `item.text` value.
To prevent this, see [#no-alphabetical-ordering](#no-alphabetical-ordering). To prevent this, see [#no-alphabetical-ordering](#no-alphabetical-ordering).
Hidden inputs will be rendered based on user selection, such as `<input type="hidden" MultiSelect provides interactivity for a list of checkbox inputs. Those
name="0" value="true" />` to mirror checkbox values and to allow MultiSelect to checkboxes will remain rendered in the DOM and are submittable within forms.
be submittable within forms. These hidden inputs can be customized with Checkbox attributes can be adjusted via the `itemToInput` prop.
the `combineValues` or `itemToInput` props.
<MultiSelect titleText="Contact" label="Select contact methods..." <MultiSelect titleText="Contact" label="Select contact methods..."
items="{[{id: "0", text: "Slack"}, items="{[{id: "0", text: "Slack"},
@ -96,30 +95,8 @@ The above function sets the `name` attribute to
`Contact_0` (respective to each item's `id`) for every hidden input that `Contact_0` (respective to each item's `id`) for every hidden input that
renders, along with each respective item's `id` set to the `value` attribute. renders, along with each respective item's `id` set to the `value` attribute.
When using with the `selectedOnly` prop, you can override every hidden input to
use the same `name` attribute. This may be useful if you
wish to use `formData.getAll('contact')` in your server-side form handler.
<MultiSelect <MultiSelect
itemToInput={(item) => ({name: 'contact', value: item.id})} itemToInput={(item) => ({name: 'contact', value: item.id})}
selectedOnly
titleText="Contact"
label="Select contact methods..."
items="{[
{id: "0", text: "Slack"},
{id: "1", text: "Email"},
{id: "2", text: "Fax"}
]}"
/>
## Combine values into a single input
With the `combineValues` prop, all selected items' values will render as a
comma-separated string within a single hidden input. A custom delimiter can
alternatively be passed in.
<MultiSelect
combineValues
titleText="Contact" titleText="Contact"
label="Select contact methods..." label="Select contact methods..."
items="{[ items="{[

View file

@ -23,25 +23,10 @@
/** /**
* Override the item name, title, labelText, or value passed to the user-selectable checkbox input as well as the hidden inputs. * 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?: * @type {(item: MultiSelectItem) => { name?: string; labelText?: any; title?: string; value?: string }}
* string; value?: string }}
*/ */
export let itemToInput = (item) => {}; export let itemToInput = (item) => {};
/**
* Set to `true` to only render selected options as hidden inputs for form submission.
* @type {boolean}
*/
export let selectedOnly = false
/**
* Combine selected items as comma-separated values when submitted in a form.
* If set to `true`, the default separator is a comma `,`.
* Pass in a string to override the separator.
* @type {false | true | string}
*/
export let combineValues = false
/** /**
* Set the selected ids * Set the selected ids
* @type {ReadonlyArray<MultiSelectItemId>} * @type {ReadonlyArray<MultiSelectItemId>}
@ -498,7 +483,7 @@
<ListBoxMenuIcon open="{open}" translateWithId="{translateWithId}" /> <ListBoxMenuIcon open="{open}" translateWithId="{translateWithId}" />
{/if} {/if}
</ListBoxField> </ListBoxField>
{#if open} <div style:display="{open ? "block" : "none"}">
<ListBoxMenu <ListBoxMenu
aria-label="{ariaLabel}" aria-label="{ariaLabel}"
id="{id}" id="{id}"
@ -548,17 +533,7 @@
</ListBoxMenuItem> </ListBoxMenuItem>
{/each} {/each}
</ListBoxMenu> </ListBoxMenu>
{:else} </div>
{#if combineValues}
{@const items = checked.map(el => el.id).join(typeof combineValues ===
'string' ? combineValues : ',')}
<input type="hidden" name={titleText} value="{items}">
{:else}
{#each selectedOnly ? checked : sortedItems as item (item.id)}
<input type="hidden" name="{item.id}" value={item.checked} {...itemToInput(item)} />
{/each}
{/if}
{/if}
</ListBox> </ListBox>
{#if !inline && !invalid && !warn && helperText} {#if !inline && !invalid && !warn && helperText}
<div <div

View file

@ -37,20 +37,6 @@ export interface MultiSelectProps extends RestProps {
value?: string; value?: string;
}; };
/**
* Set to `true` to only render selected options as hidden inputs for form submission.
* @default false
*/
selectedOnly?: boolean;
/**
* Combine selected items as comma-separated values when submitted in a form.
* If set to `true`, the default separator is a comma `,`.
* Pass in a string to override the separator.
* @default false
*/
combineValues?: false | true | string;
/** /**
* Set the selected ids * Set the selected ids
* @default [] * @default []