问题
I need to add "Select All" option in my multi-select. It should be displayed if there is at least 1 filtered option. Click on "Select All" should then add only filtered options (not all options necessarily) to already selected options.
- Input is empty, so all options are "filtered":
Clicking on Select All option would then add all options to selected options.
- Input contains "custom", so only one option remains::
Clicking on Select All option would then add only that one option to selected options.
It was easy to add "Select all" option that adds all initial options, but that isn't the solution to my problem. I managed to partially solve my problem by manually filtering options and storing them filtered in component's state, but I hope there is a simpler solution.
回答1:
I would use a combination of filterOption
, InputChange
and onChange
props:
- In
InputChange
you will catch theinputValue
every time the user changes it and store it into the state. This value will be reused inonChange
. - You need to change the initial
filterOption
to display yourSelect all
all the time. Original logic is ifinputValue
isnull
returnstrue
else returnstrue
isinputValue
is included in option label or value. Before doing this logic, we had an other condition where if option value corresponds to yourSelect all
option then returnstrue
right away. - In
onChange
; by default the returned options are those received. Then if an option has been selected (as it's multiple it could be removed) and this option isSelect all
, your returned value should be a copy of all the options and filter them by theinputValue
.
Maybe there's a simplest way to do it but I think this one it pretty effective:
onChange = (opt, { option }) => {
let newOpts = opt;
let string = this.state.searchField;
if (option && option.value === "all") {
let filteredOptions = clone(options);
filteredOptions = filteredOptions.filter(
filteredOption =>
isIncludingString(string, filteredOption) &&
!newOpts.includes(filteredOption)
);
string = null;
newOpts = newOpts
.concat(filteredOptions)
.filter(newOpt => newOpt.value !== "all");
}
this.setState({
searchField: string,
values: newOpts
});
};
onInputChange = (string, { action }) => {
if (action === "input-change") {
this.setState({
searchField: string
});
}
};
filterOption = ({ label, value }, string) => {
if (value === "all") {
return true;
} else if (string) {
return label.includes(string) || value.toString().includes(string);
} else {
return true;
}
};
Important note, in my example I use
clone
fromlodash
Below the isIncludingString
function used in onChange
.
function isIncludingString(string, option) {
let result = false;
if (
!string ||
option.label.toString().includes(string) ||
option.value.toString().includes(string)
) {
result = true;
}
return result;
}
Here a live example.
来源:https://stackoverflow.com/questions/57698868/react-select-ismulti-select-all-filtered-options