diff --git a/.all-contributorsrc b/.all-contributorsrc index d463639e76a8..193515950cd7 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -1472,6 +1472,15 @@ ] }, { + "login": "jesnajoseijk", + "name": "jesnajoseijk", + "avatar_url": "https://avatars.githubusercontent.com/u/38346258?v=4", + "profile": "https://github.com/jesnajoseijk", + "contributions": [ + "code" + ] + }, + { "login": "Jawahars", "name": "Jawahar S", "avatar_url": "https://avatars.githubusercontent.com/u/4353146?v=4", diff --git a/README.md b/README.md index 22a145a5dce2..7da9ea03bbc9 100644 --- a/README.md +++ b/README.md @@ -282,6 +282,7 @@ check out our [Contributing Guide](/.github/CONTRIBUTING.md) and our
Anjana M R

💻
Joseph Schultz

💻
anjaly0606

💻 +
jesnajoseijk

💻
Jawahar S

💻 diff --git a/packages/react/src/components/MultiSelect/MultiSelect.tsx b/packages/react/src/components/MultiSelect/MultiSelect.tsx index 685b3e7226ac..262f644734b7 100644 --- a/packages/react/src/components/MultiSelect/MultiSelect.tsx +++ b/packages/react/src/components/MultiSelect/MultiSelect.tsx @@ -15,7 +15,13 @@ import { } from 'downshift'; import isEqual from 'lodash.isequal'; import PropTypes, { ReactNodeLike } from 'prop-types'; -import React, { ForwardedRef, useContext, useRef, useState } from 'react'; +import React, { + ForwardedRef, + useContext, + useRef, + useState, + useMemo, +} from 'react'; import ListBox, { ListBoxSize, ListBoxType, @@ -373,14 +379,28 @@ const MultiSelect = React.forwardRef( selectedItems: selected, }); + // Filter out items with an object having undefined values + const filteredItems = useMemo(() => { + return items.filter((item) => { + if (typeof item === 'object' && item !== null) { + for (const key in item) { + if (Object.hasOwn(item, key) && item[key] === undefined) { + return false; // Return false if any property has an undefined value + } + } + } + return true; // Return true if item is not an object with undefined values + }); + }, [items]); + const selectProps: UseSelectProps = { ...downshiftProps, stateReducer, isOpen, - itemToString: (items) => { + itemToString: (filteredItems) => { return ( - (Array.isArray(items) && - items + (Array.isArray(filteredItems) && + filteredItems .map(function (item) { return itemToString(item); }) @@ -389,7 +409,7 @@ const MultiSelect = React.forwardRef( ); }, selectedItem: controlledSelectedItems, - items, + items: filteredItems, isItemDisabled(item, _index) { return (item as any).disabled; }, @@ -627,7 +647,7 @@ const MultiSelect = React.forwardRef( const itemsSelectedText = selectedItems.length > 0 && - selectedItems.map((item) => (item as selectedItemType).text); + selectedItems.map((item) => (item as selectedItemType)?.text); return (
@@ -701,46 +721,47 @@ const MultiSelect = React.forwardRef( {isOpen && // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - sortItems!(items, sortOptions as SortItemsOptions).map( - (item, index) => { - const isChecked = - selectedItems.filter((selected) => isEqual(selected, item)) - .length > 0; - - const itemProps = getItemProps({ - item, - // we don't want Downshift to set aria-selected for us - // we also don't want to set 'false' for reader verbosity's sake - ['aria-selected']: isChecked, - }); - const itemText = itemToString(item); - - return ( - -
- - {itemToElement ? ( - - ) : ( - itemText - )} - -
-
- ); - } - )} + sortItems!( + filteredItems, + sortOptions as SortItemsOptions + ).map((item, index) => { + const isChecked = + selectedItems.filter((selected) => isEqual(selected, item)) + .length > 0; + + const itemProps = getItemProps({ + item, + // we don't want Downshift to set aria-selected for us + // we also don't want to set 'false' for reader verbosity's sake + ['aria-selected']: isChecked, + }); + const itemText = itemToString(item); + + return ( + +
+ + {itemToElement ? ( + + ) : ( + itemText + )} + +
+
+ ); + })}
{itemsCleared && ( diff --git a/packages/react/src/components/MultiSelect/__tests__/MultiSelect-test.js b/packages/react/src/components/MultiSelect/__tests__/MultiSelect-test.js index 721cc7ffb47f..d90f77d8ee68 100644 --- a/packages/react/src/components/MultiSelect/__tests__/MultiSelect-test.js +++ b/packages/react/src/components/MultiSelect/__tests__/MultiSelect-test.js @@ -37,6 +37,27 @@ describe('MultiSelect', () => { await expect(container).toHaveNoACViolations('MultiSelect'); }); }); + it('does not render items with undefined values', async () => { + const items = [{ text: 'joey' }, { text: 'johnny' }, { text: undefined }]; + const label = 'test-label'; + render( + (item ? item.text : '')} + /> + ); + + const labelNode = screen.getByRole('combobox'); + await userEvent.click(labelNode); + + expect(screen.getByRole('option', { name: 'joey' })).toBeInTheDocument(); + expect(screen.getByRole('option', { name: 'johnny' })).toBeInTheDocument(); + expect( + screen.queryByRole('option', { name: 'undefined' }) + ).not.toBeInTheDocument(); + }); it('should initially render with a given label', () => { const items = generateItems(4, generateGenericItem);