Javascript 反应输入复选框选择所有组件

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/32641541/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 14:01:39  来源:igfitidea点击:

React input checkbox select all component

javascriptreactjs

提问by ThomasReggi

I'm trying to build a proper react input checkbox select all component. The idea is that there is a component <InputCheckboxAll>and <InputCheckbox>and I'd be able to check the <InputCheckboxAll>and all of the <InputCheckbox>would be selected as well.

我正在尝试构建一个正确的反应输入复选框选择所有组件。这个想法是有一个组件<InputCheckboxAll><InputCheckbox>我将能够检查<InputCheckboxAll>所有的<InputCheckbox>都将被选中。

I'm having two issues.

我有两个问题。

  • If <InputCheckboxAll>is checked I can't unselect any of the <InputCheckbox>.
  • If all of the <InputCheckbox>are checked then <InputCheckboxAll>should be checked.
  • 如果<InputCheckboxAll>选中,我无法取消选择任何<InputCheckbox>.
  • 如果所有的<InputCheckbox>都被检查,那么<InputCheckboxAll>应该检查。

Here's the example.

这是示例。

var InputCheckboxAll = React.createClass({
  handleChange: function (event) {
    this.props.handleChange(event)
  },
  render: function () {
    return (
    <input
           type='checkbox'
           {...this.props}
           onChange={this.handleChange} />
    )
  }
})

var InputCheckbox = React.createClass({
  getInitialState: function () {
    return {
      checked: this.props.checked
    }
  },
  render: function () {
    var checkedValue = this.props.allChecked ? true : this.state.checked
    return (
    <input
           checked={checkedValue}
           type='checkbox'
           {...this.props}/>
    )
  }
})

var Test = React.createClass({
  getInitialState: function () { return {allChecked: false}; },
  handleChange: function (event) {
    var $elm = $(event.target)
    var checked = $elm.prop('checked')
    this.setState({
      allChecked: checked
    })
  },
  render: function () {
    return (
    <div>
      Select All: <InputCheckboxAll handleChange={this.handleChange}/><br/>
      <InputCheckbox allChecked={this.state.allChecked}/><br/>
      <InputCheckbox allChecked={this.state.allChecked}/><br/>
      <InputCheckbox allChecked={this.state.allChecked}/><br/>
    </div>
    )
  }
})

React.render(<Test/>, document.body)

回答by J3Y

I think there could be some modifications to your implementation to achieve the desired results in a more React'esqueform.

我认为可以对您的实现进行一些修改,以更React 的形式实现所需的结果。

What you should get rid of first, is the InputCheckboxAllcheckbox class, and the allCheckedprop of the InputCheckboxclass. A checkbox is a relatively dumb element, it should not know about concepts such as Everything is selected.

您首先应该摆脱的是InputCheckboxAll复选框类和类的allChecked道具InputCheckbox。复选框是一个相对愚蠢的元素,它不应该了解诸如Everything is selected.

Instead, the checkbox should be implemented as an item that is simply either checkedor unchecked.

取而代之的是,复选框应该被实现为一个简单的选中或未选中的项目

var InputCheckbox = React.createClass({
  getDefaultProps: function () {
    return {
      checked: false
    }
  },
  render: function () {
    return (
    <input
           checked={this.props.checked}
           type='checkbox'
           {...this.props}/>
    )
  }
})

The state of your app (concepts such as All Selected) should be managed from the main App, keeping lower level elements stateless. The state of the main app can simply represent the checkedstatus of each of your checkboxes:

您的应用程序的状态(例如All Selected 的概念)应该从主应用程序管理,保持较低级别的元素无状态。主应用程序的状态可以简单地表示每个复选框的选中状态:

  getInitialState: function () { 
      return {
        // 3 checkboxes, all initialized as unchecked
        checked: [false, false, false]
      }; 
  },

Now, you can recreate the render function to draw 3 checkboxes, plus your select all checkbox. Each <InputCheckbox>can be binded to its own data in the this.state.checkedarray. When the <Inputcheckbox>changes, we bind an index to the change handler, so we know which array element to modify.

现在,您可以重新创建渲染函数来绘制 3 个复选框,以及您的全选复选框。每个<InputCheckbox>都可以绑定到this.state.checked数组中自己的数据。当<Inputcheckbox>更改时,我们将索引绑定到更改处理程序,因此我们知道要修改哪个数组元素。

  render: function () {
    // Recalculate if everything is checked each render, instead of storing it
    var isAllChecked = this.state.checked.filter(function(c) {
        return c;
    }).length === this.state.checked.length;

    return (
    <div>
      Select All: <InputCheckbox 
               onChange={this.selectAll} 
               checked={isAllChecked}/><br/>

      <InputCheckbox 
               checked={this.state.checked[0]} 
               onChange={this.handleChange.bind(this, 0)}/><br/>
      <InputCheckbox 
               checked={this.state.checked[1]} 
               onChange={this.handleChange.bind(this, 1)}/><br/>
      <InputCheckbox 
               checked={this.state.checked[2]} 
               onChange={this.handleChange.bind(this, 2)}/><br/>
    </div>
    )
  }

You don't need to store any state related to All Selected. Instead, it would be better to recalculate if everything is selected or not during every render. When the Select Allcheckbox is checked, we simply set every element of this.state.checkedto true.

您不需要存储与All Selected相关的任何状态。相反,最好在每次渲染期间重新计算是否选择了所有内容。当Select All复选框被选中时,我们只需将 的每个元素设置this.state.checked为 true。

This also has the advantage of when you manually select all the checkboxes, the select all checkbox will check itself.

这还有一个优点,当您手动选择所有复选框时,全选复选框将自行检查。

Here's a sample implementation: https://jsfiddle.net/rsupvxry/

这是一个示例实现:https: //jsfiddle.net/rsupvxry/

回答by Venkat.R

I came across to this thread very late. Below solution works for me with below structure.

我很晚才接触到这个线程。以下解决方案适用于以下结构。

There are 3 components which makes this feature clean and reusable.

有 3 个组件可以使此功能干净且可重用。

  1. CheckBox - Reusable Component
  2. CheckBoxList - Reusable Component
  3. CityList - End level where you can create states list or any list by cloning this.
  1. CheckBox - 可重用组件
  2. CheckBoxList - 可重用组件
  3. CityList - 您可以通过克隆创建州列表或任何列表的结束级别。

Stack Blitz with Module - https://stackblitz.com/edit/react-check-box-list

使用模块堆叠闪电战 - https://stackblitz.com/edit/react-check-box-list

Standlone Code is below

独立代码如下

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
        <title>React: Select All or DeSelect All</title>
        <script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
        <script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
        <script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
        <script type="text/babel">
            function CheckBox({name, value, tick, onCheck}) {
                return (
                    <label>
                        <input
                            name={name}
                            type="checkbox"
                            value={value}
                            checked={tick || false}
                            onChange={onCheck}
                        />
                        {value}
                    </label>
                );
            }

            function CheckBoxList ({options, isCheckedAll, onCheck}) {
                const checkBoxOptions = (
                    <div className="checkbox-list">
                        {options.map((option, index) => {
                            return (
                                <CheckBox key={index} name={option.name} value={option.value} tick={option.checked} onCheck={(e) => onCheck(option.value, e.target.checked)} />
                            );
                        })}
                    </div>
                );

                return (
                    <div className="checkbox-list">
                        <CheckBox name="select-all" value="ALL" tick={isCheckedAll} onCheck={(e) => onCheck('all', e.target.checked)} />
                        {checkBoxOptions}
                    </div>
                );
            }

            class CityList extends React.Component {
                constructor(props) {
                    super(props);

                    this.state = {
                        isAllSelected: false,
                        checkList: [
                            {
                                name: "city",
                                value: "bangalore",
                                checked: false,
                            },
                            {
                                name: "city",
                                value: "chennai",
                                checked: false,
                            },
                            {
                                name: "city",
                                value: "delhi",
                                checked: false,
                            }
                        ]
                    };
                }

                onCheckBoxChange(checkName, isChecked) {
                    let isAllChecked = (checkName === 'all' && isChecked);
                    let isAllUnChecked = (checkName === 'all' && !isChecked);
                    const checked = isChecked;

                    const checkList = this.state.checkList.map((city, index) => {
                        if(isAllChecked || city.value === checkName) {
                            return Object.assign({}, city, {
                                checked,
                            });
                        } else if (isAllUnChecked) {
                            return Object.assign({}, city, {
                                checked: false,
                            });
                        }

                        return city;
                    });

                    let isAllSelected = (checkList.findIndex((item) => item.checked === false) === -1) || isAllChecked;

                    this.setState({
                        checkList,
                        isAllSelected,
                    });

                }

                render() {
                    return (<CheckBoxList options={this.state.checkList} isCheckedAll={this.state.isAllSelected} onCheck={this.onCheckBoxChange.bind(this)} />);
                }
            }

            ReactDOM.render(
                <CityList />,
                document.getElementById('root')
            );
        </script>
    </head>
    <body>
        <div id="root"></div>
    </body>
</html>

回答by Alexej

There is a simple package that solves this problem grouped-checkboxes.

有一个简单的包可以解决这个问题grouped-checkboxes

In your case the render function will look like this:

在您的情况下,渲染函数将如下所示:

render: function () {
  return (
    <CheckboxGroup>
      Select All: <AllCheckerCheckbox /><br/>
      <Checkbox id="option-0" onChange={this.handleChange.bind(this, 0)}/><br/>
      <Checkbox id="option-1" onChange={this.handleChange.bind(this, 1)}/><br/>
      <Checkbox id="option-2" onChange={this.handleChange.bind(this, 2)}/><br/>
    </CheckboxGroup>
  )
}

More examples see Codesandbox example

更多示例参见Codesandbox 示例