简体   繁体   English

React-select isMulti 选择所有过滤选项

[英]React-select isMulti select all filtered options

I need to add "Select All" option in my multi-select.我需要在我的多选中添加“全选”选项。 It should be displayed if there is at least 1 filtered option.如果至少有 1 个过滤选项,则应显示它。 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.我设法通过手动过滤选项并将它们存储在组件状态中来部分解决我的问题,但我希望有一个更简单的解决方案。

I would use a combination of filterOption , InputChange and onChange props: 我将使用filterOptionInputChangeonChange道具的组合:

  • In InputChange you will catch the inputValue every time the user changes it and store it into the state. InputChange您将在用户每次更改inputValue并将其存储到状态时捕获到它。 This value will be reused in onChange . 此值将在onChange重用。
  • You need to change the initial filterOption to display your Select all all the time. 您需要更改初始filterOption才能filterOption显示“ Select all ”。 Original logic is if inputValue is null returns true else returns true is inputValue is included in option label or value. 原始的逻辑是,如果inputValuenull返回true否则返回trueinputValue被包含在选项标签或值。 Before doing this logic, we had an other condition where if option value corresponds to your Select all option then returns true right away. 在执行此逻辑之前,我们还有另一个条件,即如果选项值对应于“ Select all选”选项,则立即返回true
  • In onChange ; 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 . 然后,如果选择了一个选项(可能会删除多个选项),并且此选项是Select all ,则您返回的值应该是所有选项的副本,并使用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 重要说明,在我的示例中,我使用来自lodash clone

Below the isIncludingString function used in onChange . onChange使用的isIncludingString函数下面。

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 . 这里有一个活生生的例子

Here is the function that I used to convert all my existing multi selecters:这是我用来转换所有现有多选择器的函数:

import React from "react";
import ReactSelect from "react-select";

const addSelectAllOptionIfIsMulti = (props) => {
  if (!props.isMulti) {
    return props;
  }
  const selectAllOption = {}; // just an object to be compared to by reference

  const getOptionLabel = (obj) =>
    obj === selectAllOption
      ? "Select all"
      : props.getOptionLabel
      ? props.getOptionLabel(obj)
      : obj.label;

  const getOptionValue = (obj) =>
    obj === selectAllOption
      ? selectAllOption
      : props.getOptionValue
      ? props.getOptionValue(obj)
      : obj.value;

  const onChange = (values) => {
    const selectedOptions = values.includes(selectAllOption)
      ? props.options
      : values;
    props.onChange(selectedOptions);
  };

  const options =
    props.options.length === props.value?.length
      ? props.options
      : [selectAllOption, ...props.options];

  return { ...props, getOptionLabel, getOptionValue, onChange, options };
};

function Select({...props}){
  return <ReactSelect {...addSelectAllOptionIfIsMulti(props)}/>
}
export default Select;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM