Skip to content

Commit d8a2d9d

Browse files
committed
fix(pf4): add nested filtering for select
1 parent abbcc85 commit d8a2d9d

File tree

2 files changed

+58
-18
lines changed

2 files changed

+58
-18
lines changed

packages/pf4-component-mapper/src/select/select/menu.js

Lines changed: 25 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -117,8 +117,26 @@ const Menu = ({
117117
menuPortalTarget,
118118
menuIsPortal,
119119
selectToggleRef,
120+
originalOptions,
120121
}) => {
121-
const filteredOptions = isSearchable ? filterOptions(options, filterValue) : options;
122+
const filteredOptions = isSearchable ? filterOptions(originalOptions, filterValue) : originalOptions;
123+
124+
let index = 0;
125+
126+
const createOption = (item) => {
127+
index++;
128+
129+
const itemProps = getItemProps({
130+
item,
131+
index,
132+
isActive: highlightedIndex === index,
133+
isSelected: isMulti ? !!selectedItem.find(({ value }) => item.value === value) : selectedItem === item.value,
134+
onMouseUp: (e) => e.stopPropagation(), // we need this to prevent issues with portal menu not selecting a option
135+
});
136+
137+
return <Option key={item.key || item.value || (typeof item.label === 'string' && item.label) || item} item={item} {...itemProps} />;
138+
};
139+
122140
const menuItems = (
123141
<ul className={`pf-c-select__menu${menuIsPortal ? ' ddorg__pf4-component-mapper__select-menu-portal' : ''}`}>
124142
{filteredOptions.length === 0 && (
@@ -130,11 +148,12 @@ const Menu = ({
130148
isFetching={isFetching}
131149
/>
132150
)}
133-
{filteredOptions.map((item, index) => {
134-
if (item.group) {
151+
{filteredOptions.map((item, arrayIndex) => {
152+
if (item.options) {
135153
return (
136-
<div className="pf-c-select__menu-group" key={`group-${index}`}>
137-
<div className="pf-c-select__menu-group-title">{item.group}</div>
154+
<div className="pf-c-select__menu-group" key={`group-${arrayIndex}`}>
155+
<div className="pf-c-select__menu-group-title">{item.label}</div>
156+
{item.options.map((nestedItem) => createOption(nestedItem))}
138157
</div>
139158
);
140159
}
@@ -143,14 +162,7 @@ const Menu = ({
143162
return <hr className="pf-c-divider" key={`divider-${index}`} />;
144163
}
145164

146-
const itemProps = getItemProps({
147-
item,
148-
index,
149-
isActive: highlightedIndex === index,
150-
isSelected: isMulti ? !!selectedItem.find(({ value }) => item.value === value) : selectedItem === item.value,
151-
onMouseUp: (e) => e.stopPropagation(), // we need this to prevent issues with portal menu not selecting a option
152-
});
153-
return <Option key={item.key || item.value || (typeof item.label === 'string' && item.label) || item} item={item} {...itemProps} />;
165+
return createOption(item);
154166
})}
155167
</ul>
156168
);

packages/pf4-component-mapper/src/select/select/select.js

Lines changed: 33 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -69,11 +69,36 @@ const itemToString = (value, isMulti, showMore, handleShowMore, handleChange) =>
6969
};
7070

7171
// TODO fix the value of internal select not to be an array all the time. It forces the filter value to be an array and it crashes sometimes.
72-
const filterOptions = (options, filterValue = '') =>
73-
options.filter(({ label }) => {
74-
const filter = Array.isArray(filterValue) && filterValue.length > 0 ? filterValue[0] : filterValue;
75-
return label.toLowerCase().includes(filter.toLowerCase());
76-
});
72+
const filterOptions = (options, filterValue = '') => {
73+
const filter = (Array.isArray(filterValue) && filterValue.length > 0 ? filterValue[0] : filterValue).toLowerCase();
74+
75+
if (!filter) {
76+
return options;
77+
}
78+
79+
return options
80+
.map((option) => {
81+
if (option.options) {
82+
const filteredNested = option.options.map((option) => (option.label?.toLowerCase().includes(filter) ? option : null)).filter(Boolean);
83+
84+
if (filteredNested.length === 0) {
85+
return null;
86+
}
87+
88+
return {
89+
...option,
90+
options: filteredNested,
91+
};
92+
}
93+
94+
if (option.label?.toLowerCase().includes(filter)) {
95+
return option;
96+
}
97+
98+
return null;
99+
})
100+
.filter(Boolean);
101+
};
77102

78103
const getValue = (isMulti, option, value) => {
79104
if (!isMulti || !option) {
@@ -154,6 +179,7 @@ const InternalSelect = ({
154179
loadingMessage,
155180
menuPortalTarget,
156181
menuIsPortal,
182+
originalOptions,
157183
...props
158184
}) => {
159185
const [showMore, setShowMore] = useState(false);
@@ -223,6 +249,7 @@ const InternalSelect = ({
223249
menuPortalTarget={menuPortalTarget}
224250
menuIsPortal={menuIsPortal}
225251
selectToggleRef={selectToggleRef}
252+
originalOptions={originalOptions}
226253
/>
227254
)}
228255
</div>
@@ -257,6 +284,7 @@ InternalSelect.propTypes = {
257284
loadingMessage: PropTypes.node,
258285
menuPortalTarget: PropTypes.any,
259286
menuIsPortal: PropTypes.bool,
287+
originalOptions: PropTypes.array,
260288
};
261289

262290
const Select = ({ menuIsPortal, ...props }) => {

0 commit comments

Comments
 (0)