Skip to content

Commit

Permalink
fix(MultiSelect): add selectedItems prop for fully controlled component
Browse files Browse the repository at this point in the history
  • Loading branch information
akdetrick committed May 14, 2024
1 parent 5ea7d95 commit e2f14f1
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 3 deletions.
21 changes: 19 additions & 2 deletions src/MultiSelect/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,12 @@ const itemToString = (item) =>
const isSelected = (selectedItems, item) =>
selectedItems.map(itemToString).includes(itemToString(item));

/**
* Gets full item element by its `value` prop
*/
const getSelectedItems = (values, items) =>
items.filter((item) => values.includes(item.props.value));

/**
* Get new list of `MenuSelect.item` components that are selected after
* user dismisses a token.
Expand All @@ -45,6 +51,7 @@ const MultiSelect = ({
name,
label,
children,
selectedItems: selectedItemsProp = [],
onSelectedItemsChange: onChangeProp = noop,
fieldValue,
errorText,
Expand All @@ -60,7 +67,7 @@ const MultiSelect = ({
removeSelectedItem,
selectedItems,
} = useMultipleSelection({
initialSelectedItems: [],
initialSelectedItems: getSelectedItems(selectedItemsProp, items),
stateReducer: (state, actionAndChanges) => {
const { type, changes, selectedItem } = actionAndChanges;
let newSelectedItems = [...new Set(changes.selectedItems)];
Expand Down Expand Up @@ -176,7 +183,12 @@ const MultiSelect = ({

return (
<div className="nds-multiselect" data-testid={testId}>
<input type="hidden" name={name} id={name} value={fieldValue} />
<input
type="hidden"
name={name}
id={name}
value={fieldValue || selectedItems.map(itemToString).join(",")}
/>
<DropdownTrigger
isOpen={isOpen}
labelText={label}
Expand Down Expand Up @@ -249,6 +261,11 @@ MultiSelect.propTypes = {
name: PropTypes.string.isRequired,
/** Label for the select control */
label: PropTypes.string.isRequired,
/**
* When passed, the MultiSelect becomes fully controlled.
* Use `onSelectedItemsChange` to manage this value.
*/
selectedItems: PropTypes.arrayOf(PropTypes.string),
/**
* Change callback for user actions that select or deselect items.
* Called with an array of selected item values.
Expand Down
38 changes: 37 additions & 1 deletion src/MultiSelect/index.stories.js
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,43 @@ SettingTheFieldValue.parameters = {
docs: {
description: {
story:
"Adding and removing selected items is uncontrolled and internal to `MultiSelect`. To set the actual form field value, use `fieldValue`. To update `fieldValue`, you may use `onSelectedItemsChange`.",
"By default, `fieldValue` will populate the value of the underlying hidden input as a string of selected values separated by `,`. You may use the `fieldValue` prop to change the formatting of the string value applied to the hidden input.",
},
},
};

export const ControlledSelectedItems = () => {
const [selectedItems, setSelectedItems] = useState(["truck", "coffee"]);
const handleSelectedItemsChange = (selectedItems) => {
setSelectedItems(selectedItems);
};
return (
<MultiSelect
name="controlled-product-field"
label="Favorite Icons"
selectedItems={selectedItems}
onSelectedItemsChange={handleSelectedItemsChange}
>
<MultiSelect.Item value="coffee">
<span className="narmi-icon-coffee padding--right--xs" /> Coffee
</MultiSelect.Item>
<MultiSelect.Item value="film">
<span className="narmi-icon-film padding--right--xs" /> Film
</MultiSelect.Item>
<MultiSelect.Item value="truck">
<span className="narmi-icon-truck padding--right--xs" /> Truck
</MultiSelect.Item>
<MultiSelect.Item value="blob">
<span className="narmi-icon-blob padding--right--xs" /> Blob
</MultiSelect.Item>
</MultiSelect>
);
};
ControlledSelectedItems.parameters = {
docs: {
description: {
story:
"By default, the `MultiSelect` component behaves like an uncontrolled component. To make this component fully controlled, pass in `selectedItems` and update the list of values by using `onSelectedItemsChange`",
},
},
};
Expand Down

0 comments on commit e2f14f1

Please sign in to comment.