Skip to content

Commit

Permalink
fix(Multiselect): optimize handling of grouped options by flattening …
Browse files Browse the repository at this point in the history
…structure (#7357)

* remove: delete createGroupChildren function

* refactor: optimize handling of grouped options by flattening structure
  • Loading branch information
KumJungMin authored Oct 19, 2024
1 parent 871a3a3 commit d9e35ad
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 82 deletions.
65 changes: 24 additions & 41 deletions components/lib/multiselect/MultiSelect.js
Original file line number Diff line number Diff line change
Expand Up @@ -386,28 +386,11 @@ export const MultiSelect = React.memo(

if (event.checked) {
value = [];
} else {
const validOptions = visibleOptions.filter((option) => isValidOption(option) && !isOptionDisabled(option));

if (visibleOptions) {
const selectedOptions = visibleOptions.filter((option) => isOptionDisabled(option) && isSelected(option));

value = selectedOptions.map((option) => getOptionValue(option));
}
} else if (visibleOptions) {
const options = visibleOptions.filter((option) => !isOptionDisabled(option) || isSelected(option));

if (props.optionGroupLabel) {
value = [];
options.forEach(
(optionGroup) =>
(value = [
...value,
...getOptionGroupChildren(optionGroup)
.filter((option) => !isOptionDisabled(option))
.map((option) => getOptionValue(option))
])
);
} else {
value = options.map((option) => getOptionValue(option));
if (validOptions) {
value = validOptions.map((option) => getOptionValue(option));
}
}

Expand Down Expand Up @@ -622,21 +605,7 @@ export const MultiSelect = React.memo(
return false;
}

const options = visibleOptions.filter((option) => !isOptionDisabled(option));

if (props.optionGroupLabel) {
let areAllSelected = true;

for (let optionGroup of options) {
const visibleOptionsGroupChildren = getOptionGroupChildren(optionGroup).filter((option) => !isOptionDisabled(option));

if (visibleOptionsGroupChildren.some((option) => !isSelected(option)) === true) {
areAllSelected = false;
}
}

return areAllSelected;
}
const options = visibleOptions.filter((option) => !isOptionDisabled(option) && isValidOption(option));

return !options.some((option) => !isSelected(option));
};
Expand Down Expand Up @@ -697,7 +666,7 @@ export const MultiSelect = React.memo(
};

const isOptionGroup = (option) => {
return props.optionGroupLabel && option.optionGroup && option.group;
return props.optionGroupLabel && option.group;
};

const hasSelectedOption = () => {
Expand Down Expand Up @@ -937,12 +906,14 @@ export const MultiSelect = React.memo(
};

const getVisibleOptions = () => {
const options = props.optionGroupLabel ? flatOptions(props.options) : props.options;

if (hasFilter) {
const filterValue = filterState.trim().toLocaleLowerCase(props.filterLocale);
const searchFields = props.filterBy ? props.filterBy.split(',') : [props.optionLabel || 'label'];

if (props.optionGroupLabel) {
let filteredGroups = [];
const filteredGroups = [];

for (let optgroup of props.options) {
let filteredSubOptions = FilterService.filter(getOptionGroupChildren(optgroup), searchFields, filterValue, props.filterMatchMode, props.filterLocale);
Expand All @@ -952,13 +923,25 @@ export const MultiSelect = React.memo(
}
}

return filteredGroups;
return flatOptions(filteredGroups);
}

return FilterService.filter(props.options, searchFields, filterValue, props.filterMatchMode, props.filterLocale);
return FilterService.filter(options, searchFields, filterValue, props.filterMatchMode, props.filterLocale);
}

return props.options;
return options;
};

const flatOptions = (options) => {
return (options || []).reduce((result, option, index) => {
result.push({ ...option, group: true, index });

const optionGroupChildren = getOptionGroupChildren(option);

optionGroupChildren && optionGroupChildren.forEach((o) => result.push(o));

return result;
}, []);
};

React.useImperativeHandle(ref, () => ({
Expand Down
45 changes: 4 additions & 41 deletions components/lib/multiselect/MultiSelectPanel.js
Original file line number Diff line number Diff line change
Expand Up @@ -104,39 +104,6 @@ export const MultiSelectPanel = React.memo(
}
};

const createGroupChildren = (optionGroup, style) => {
const groupChildren = props.getOptionGroupChildren(optionGroup);

return groupChildren.map((option, j) => {
const optionLabel = props.getOptionLabel(option);
const optionKey = j + '_' + props.getOptionRenderKey(option);
const disabled = props.isOptionDisabled(option);
const selected = props.isSelected(option);

return (
<MultiSelectItem
hostName={props.hostName}
index={j}
key={optionKey}
focusedOptionIndex={props.focusedOptionIndex}
label={optionLabel}
option={option}
style={style}
template={props.itemTemplate}
selected={selected}
onClick={props.onOptionSelect}
onMouseMove={changeFocusedItemOnHover}
disabled={disabled}
className={props.itemClassName}
checkboxIcon={props.checkboxIcon}
isUnstyled={isUnstyled}
ptm={ptm}
cx={cx}
/>
);
});
};

const createEmptyFilter = () => {
const emptyFilterMessage = ObjectUtils.getJSXElement(props.emptyFilterMessage, props) || localeOption('emptyFilterMessage');

Expand Down Expand Up @@ -174,9 +141,8 @@ export const MultiSelectPanel = React.memo(
const createItem = (option, index, scrollerOptions = {}) => {
const style = { height: scrollerOptions.props ? scrollerOptions.props.itemSize : undefined };

if (props.optionGroupLabel) {
if (option.group && props.optionGroupLabel) {
const groupContent = props.optionGroupTemplate ? ObjectUtils.getJSXElement(props.optionGroupTemplate, option, index) : props.getOptionGroupLabel(option);
const groupChildrenContent = createGroupChildren(option, style);
const key = index + '_' + props.getOptionGroupRenderKey(option);
const itemGroupProps = mergeProps(
{
Expand All @@ -187,12 +153,9 @@ export const MultiSelectPanel = React.memo(
);

return (
<React.Fragment key={key}>
<li {...itemGroupProps} key={key}>
{groupContent}
</li>
{groupChildrenContent}
</React.Fragment>
<li key={key} {...itemGroupProps}>
{groupContent}
</li>
);
}

Expand Down

0 comments on commit d9e35ad

Please sign in to comment.