【问题标题】:how to disable a button if more than one or no checkbox is checked in React JS如果在 React JS 中选中多个或没有选中复选框,如何禁用按钮
【发布时间】:2021-12-31 15:13:50
【问题描述】:

我有一个表格,其中第一列的每一行都有一个复选框。如果选择了多个复选框或未选中任何复选框,我想禁用一个按钮。只有在选中1个复选框时,它应该是有效的,只有1个复选框

import React, { useState } from "react";
import "./styles.css";
function Example() {
  const [boxes, setBoxes] = useState([]);
  function handleChange(e) {
    const {
      parentNode: { children }
    } = e.target;
    const index = [...children].indexOf(e.target);
    const newState = [...boxes];
    newState[index] = !newState[index];
    setBoxes(newState);
  }
  function isDisabled() {
    const len = boxes.filter((box) => box).length;
    return len === 0 || len > 1;
  }
  return (
    <div className="App">
      <button disabled={isDisabled()}>Click Me</button>
      <table>
        <thead>
          <th>One</th>
          <th>Two</th>
          <th>Three</th>
        </thead>
        <tbody>
          <tr>
            <td>
              <input type="checkbox" onChange={handleChange} />
            </td>
            <td> two data</td>
            <td> three data</td>
          </tr>
          <tr>
            <td>
              <input type="checkbox" onChange={handleChange} />
            </td>
            <td> two data</td>
            <td> three data</td>
          </tr>
          <tr>
            <td>
              <input type="checkbox" onChange={handleChange} />
            </td>
            <td> two data</td>
            <td> three data</td>
          </tr>
        </tbody>
      </table>
    </div>
  );
}

export default Example;

如果所有复选框都在同一个父节点中,我就能完成这项工作。但在表格的情况下,每个复选框都在单独的行中。

【问题讨论】:

    标签: javascript arrays reactjs


    【解决方案1】:

    您可以为复选框分配 id 并像这样关注它们。

    import React, { useState } from "react";
    function Example() {
      const [boxes, setBoxes] = useState({});
      function handleChange(e) {
        const {
          target: { id, checked }
        } = e;
        setBoxes({ ...boxes, [id]: checked });
      }
      function isDisabled() {
        const { length } = Object.values(boxes).filter(Boolean);
        return length !== 1;
      }
      return (
        <div className="App">
          <button disabled={isDisabled()}>Click Me</button>
          <table>
            <thead>
              <th>One</th>
              <th>Two</th>
              <th>Three</th>
            </thead>
            <tbody>
              <tr>
                <td>
                  <input id="1" type="checkbox" onChange={handleChange} />
                </td>
                <td> two data</td>
                <td> three data</td>
              </tr>
              <tr>
                <td>
                  <input id="2" type="checkbox" onChange={handleChange} />
                </td>
                <td> two data</td>
                <td> three data</td>
              </tr>
              <tr>
                <td>
                  <input id="3" type="checkbox" onChange={handleChange} />
                </td>
                <td> two data</td>
                <td> three data</td>
              </tr>
            </tbody>
          </table>
        </div>
      );
    }
    
    export default Example;
    

    【讨论】:

      【解决方案2】:

      你可以给所有的复选框一个名字,这个解决方案就可以了

          import React, { useState } from "react";
      function Example() {
        const [btnStatus, setBtnStatus] = useState(true);
        function handleChange(e) {
          const elements = document.getElementsByName('checkbox');
          let checkedCount = 0;
          elements.forEach((element)=>{
            if(element.checked){
              checkedCount ++;
            }
          })
        if(checkedCount > 1 || checkedCount === 0){
          setBtnStatus(true)
        }else{
          setBtnStatus(false)
        }
        }
      
        return (
          <div className="App">
            <button disabled={btnStatus}>Click Me</button>
            <table>
              <thead>
                <th>One</th>
                <th>Two</th>
                <th>Three</th>
              </thead>
              <tbody>
                <tr>
                  <td>
                    <input name="checkbox" type="checkbox" onChange={handleChange} />
                  </td>
                  <td> two data</td>
                  <td> three data</td>
                </tr>
                <tr>
                  <td>
                    <input name="checkbox" type="checkbox" onChange={handleChange} />
                  </td>
                  <td> two data</td>
                  <td> three data</td>
                </tr>
                <tr>
                  <td>
                    <input name="checkbox" type="checkbox" onChange={handleChange} />
                  </td>
                  <td> two data</td>
                  <td> three data</td>
                </tr>
              </tbody>
            </table>
          </div>
        );
      }
      
      export default Example;
      

      【讨论】:

        【解决方案3】:

        您的初始测试(所有复选框都在同一个父节点中)正在运行,因为您认为它们都在同一个父节点中:

        const {
          parentNode: { children }
        } = e.target;
        

        其中“children”是实际的复选框。在表格示例中,每个复选框的父级只有一个子级。

        我会建议一个更灵活的解决方案,如下所示,将复选框索引作为参数发送到 onChange 处理程序:

        import React, { useState } from "react";
        
        // use props to determine the number of records
        function Example(props) {
          // make sure initial state is known and false
          const [boxes, setBoxes] = useState(new Array(props.recordsNo).fill(false));
        
          // index - the index of the checkbox
          function handleChange(index) {
            const newState = [...boxes];
            newState[index] = !newState[index];
            setBoxes(newState);
          }
          
          function isDisabled() {
            const len = boxes.filter((box) => box).length;
            return len === 0 || len > 1;
          }
        
          // records will probably come through props => generate here an example
          const records = [...Array(props.recordsNo).keys()];
          
          // generate records display 
          const rows = records.map((value, i) => {
            return (
              <tr>
                <td>
                  <input type="checkbox" onChange={() => handleChange(i)} />
                </td>
                <td> {i}</td>
                <td> two data</td>
                <td> three data</td>
              </tr>
            )
          })
        
          return (
            <div className="App">
              <button disabled={isDisabled()}>Click Me</button>
              <table>
                <thead>
                  <th>One</th>
                  <th>Two</th>
                  <th>Three</th>
                </thead>
                <tbody>
                  {rows}
                </tbody>
              </table>
            </div>
          );
        }
        
        export default Example;
        

        【讨论】:

          猜你喜欢
          • 2016-02-08
          • 2016-03-12
          • 2015-09-22
          • 2019-05-23
          • 1970-01-01
          • 2013-08-12
          • 2021-11-22
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多