React-select isMulti select all filtered options

戏子无情 提交于 2020-04-18 06:39:33

问题


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.

  1. Input is empty, so all options are "filtered":

Clicking on Select All option would then add all options to selected options.

  1. 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 InputChangeyou will catch the inputValue every time the user changes it and store it into the state. This value will be reused in onChange.
  • You need to change the initial filterOption to display your Select all all the time. Original logic is if inputValue is null returns true else returns true is inputValue is included in option label or value. Before doing this logic, we had an other condition where if option value corresponds to your Select all option then returns true 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 is Select all, your returned value should be a copy of all the options and filter them by the inputValue.

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 from lodash

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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!