Реагирующий обработчик onclick для группы флажков

#javascript #reactjs

#javascript #reactjs

Вопрос:

Я использую reactjs, и у меня есть следующий код моделирования, который упрощен, чтобы лучше понять мой вопрос:

      <span onClick={selectHandler}>Select Group 1</span>
    <ul>
      <li>
        <input type="checkbox" id="kw1" name="Group1[]" value="kw1" />
      </li>
      <li>
        <input type="checkbox" id="kw2" name="Group1[]" value="kw2" />
      </li>
      <li>
        <input type="checkbox" id="kw3" name="Group1[]" value="kw3" />
      </li>
    </ul>
    <span onClick={selectHandler}>Select Group 2</span>
    <ul>
      <li>
        <input type="checkbox" id="tr1" name="Group2[]" value="tr1" />
      </li>
      <li>
        <input type="checkbox" id="tr2" name="Group2[]" value="tr2" />
      </li>
      <li>
        <input type="checkbox" id="tr3" name="Group2[]" value="tr3" />
      </li>
    </ul>
 

Мой вопрос в том, как мне написать функцию selectHandler, чтобы выбрать все флажки в соответствии с группой. Пример, если пользователь нажмет на группу 1, будут установлены все флажки kw1, kw2 и kw3. И когда пользователь нажимает на группу 2, будут установлены все флажки tr1, tr2 и tr3.
Когда они снова нажмут на группу 1 или группу 2, флажки будут сняты в соответствии с группой соответственно

Комментарии:

1. Вы хотите, чтобы компонент был контролируемым или неконтролируемым?

Ответ №1:

Я бы сказал, что вам нужно будет прикрепить к вашим входным данным checked prop, чтобы вы могли сохранять состояние отдельно для элементов пользовательского интерфейса. Таким образом, вы можете программно установить их состояние в отдельной функции.

Редактировать:

Хорошо, я ввел это в stackblitz, кажется, у меня были некоторые орфографические ошибки: https://stackblitz.com/edit/react-vcqqif?file=src/App.js

 const CheckBoxGroup = () => {
  const [checked, setChecked] = React.useState({
    tr1: false,
    tr2: false,
    tr3: false,
  });

  function handleSelectAll() {
    setChecked((prevState) => {
      /**
       * The following converts the boolen values into an array of primitive
       * types and checks the length against the selected. If all selected then
       * deselect, otherwise select all.
       */
      const stateValues = Object.values(prevState);

      const fullLength = stateValues.length;
      const selectedLength = stateValues.filter(
        (selectedState) => selectedState
      ).length;

      if (fullLength === selectedLength) {
        return {
          tr1: false,
          tr2: false,
          tr3: false,
        };
      }

      return {
        tr1: true,
        tr2: true,
        tr3: true,
      };
    });
  }
  function handleClick(id) {
    setChecked((prevState) => ({
      ...prevState,
      [id]: !prevState[id],
    }));
  }

  return (
    <>
      <button onClick={handleSelectAll}>Select Group 2</button>
      <ul>
        <li>
          <input
            type="checkbox"
            id="tr1"
            name="Group2[]"
            value="tr1"
            checked={checked.tr1}
            onClick={() => handleClick('tr1')}
          />
        </li>
        <li>
          <input
            type="checkbox"
            id="tr2"
            name="Group2[]"
            value="tr2"
            checked={checked.tr2}
            onClick={() => handleClick('tr2')}
          />
        </li>
        <li>
          <input
            type="checkbox"
            id="tr3"
            name="Group2[]"
            value="tr3"
            checked={checked.tr3}
            onClick={() => handleClick('tr3')}
          />
        </li>
      </ul>
    </>
  );
};
 

Комментарии:

1. Просто чтобы добавить к этому, вы должны использовать button вместо элемента span для handleSelectAll было бы лучше по соображениям доступности

2. Привет, Эанна, спасибо, что уделили мне время. Я попытался реализовать это, но когда я устанавливаю один флажок, срабатывают все флажки. Если я поставлю галочку в группе выбора 2, она установит все флажки, но когда я поставлю галочку снова, она не снимет все флажки.

3. @user2601660 Извините за это, я на самом деле не проверял это, если честно, но при проверке сделанного мной редактирования кажется, что я допустил орфографическую ошибку в реквизите, который я использовал в checked . Я добавил пример его использования в stackblitz!

4. Спасибо @Eanna, код в Blitz работает отлично

Ответ №2:

Существует простой пакет, который решает эту проблему сгруппированными флажками.

В вашем случае функция рендеринга будет выглядеть следующим образом:

 <CheckboxGroup>
  Select All: <AllCheckerCheckbox /><br/>
  <Checkbox id="option-0" /><br/>
  <Checkbox id="option-1" /><br/>
  <Checkbox id="option-2" /><br/>
</CheckboxGroup>
 

Комментарии:

1. Спасибо Саймону за ваш ответ. Поддерживает ли эта библиотека сгруппированные флажки NextJS? Я попытался установить его, но получил много предупреждений, которые можно увидеть на ibb.co/tpKsTn3

2. @user2601660 Я думаю, что пока он работает, эти предупреждения вообще не имеют смысла :). Если вы считаете, что вам не нужен пакет, попробуйте создать его самостоятельно, как объяснила Эанна Джи в своем ответе.