React-select isMulti выбрать все отфильтрованные параметры

Мне нужно добавить опцию «Выбрать все» в мой множественный выбор. Он должен отображаться, если есть хотя бы 1 отфильтрованный вариант. Нажмите «Выбрать все», чтобы добавить только отфильтрованные параметры (не обязательно все параметры) к уже выбранным параметрам.

  1. Вход пуст, поэтому все параметры «фильтруются»:  введите описание изображения здесь

При нажатии на опцию «Выбрать все» все опции будут добавлены к выбранным опциям.

  1. Входные данные содержат "custom", поэтому остается только один вариант:  введите описание изображения здесь

При нажатии на опцию «Выбрать все» к выбранным опциям добавляется только этот вариант.

Было легко добавить опцию «Выбрать все», которая добавляет все начальные опции, но это не решение моей проблемы. Мне удалось частично решить мою проблему, вручную отфильтровав параметры и сохранив их отфильтрованными в состоянии компонента, но я надеюсь, что есть более простое решение.


person brklja    schedule 28.08.2019    source источник


Ответы (1)


Я бы использовал комбинацию реквизита filterOption, InputChange и onChange:

  • В InputChange вы будете ловить inputValue каждый раз, когда пользователь меняет его, и сохранять его в состоянии. Это значение будет повторно использовано в onChange.
  • Вам нужно изменить начальный filterOption, чтобы ваш Select all отображался постоянно. Исходная логика: если inputValue равно null, возвращает true, иначе возвращает true, inputValue включается в метку или значение параметра. Перед выполнением этой логики у нас было другое условие, при котором, если значение параметра соответствует вашему Select all параметру, то сразу же возвращается true.
  • В onChange; по умолчанию возвращаются те, которые были получены. Затем, если была выбрана опция (поскольку ее несколько, ее можно было удалить) и эта опция равна Select all, возвращаемое вами значение должно быть копией всех параметров и отфильтровывать их по inputValue.

Может быть, есть самый простой способ сделать это, но я думаю, что он довольно эффективен:

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;
  }
};

Важное примечание: в моем примере я использую clone из lodash

Ниже функции isIncludingString, используемой в onChange.

function isIncludingString(string, option) {
  let result = false;
  if (
    !string ||
    option.label.toString().includes(string) ||
    option.value.toString().includes(string)
  ) {
    result = true;
  }
  return result;
}

Вот живой пример.

person Laura    schedule 28.08.2019
comment
Привет, Лаура, спасибо за ответ. Решил аналогично. Существует ошибка, если вы, например, хотите выбрать все значения, содержащие 3, и после этого добавить значения, содержащие 4 предыдущих значения, которые будут перезаписаны. Я столкнулся с той же проблемой - person brklja; 29.08.2019
comment
Я все исправил. Поменял кое-что в функции onChange :) Спасибо за помощь! - person brklja; 29.08.2019
comment
Что касается проблемы, о которой вы говорите, это скорее еще одно ограничение;) вы можете обновить свой вопрос, я изменю свой код в соответствии с этим новым требованием и, возможно, помогу другим людям. - person Laura; 29.08.2019