React input复选框选择所有组件

时间:2015-09-17 23:28:11

标签: javascript reactjs

我正在尝试构建一个正确的反应输入复选框选择所有组件。我们的想法是有一个组件<InputCheckboxAll><InputCheckbox>,我可以检查<InputCheckboxAll>,并且所有<InputCheckbox>也会被选中。

我有两个问题。

  • 如果选中<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)

4 个答案:

答案 0 :(得分:8)

我认为您的实现可能会有一些修改,以更多 React'esque 形式获得所需的结果。

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

之类的概念

相反,该复选框应该实现为只需已检查取消选中的项目。

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

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

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

现在,您可以重新创建渲染功能以绘制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>
    )
  }

您无需存储与所有选定相关的任何状态。相反,如果在每次渲染期间都选择了所有内容,那么最好重新计算。选中Select All复选框后,我们只需将this.state.checked的每个元素设置为true。

这样做的另一个好处是,当您手动选中所有复选框时,全选复选框将自行检查。

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

答案 1 :(得分:1)

我很晚才接触到该线程。以下解决方案对我来说具有以下结构。

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

  1. CheckBox-可重用组件
  2. CheckBoxList-可重用组件
  3. CityList-结束级别,您可以在其中创建状态列表或任何克隆列表。

带有模块的Stack Blitz-https://stackblitz.com/edit/react-check-box-list

标准代码在下面

<!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>

答案 2 :(得分:0)

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

在您的情况下,渲染功能将如下所示:

#include <functional>

class U {
public:
    template <class C>
    U(C* p)
        : f{[p]{ p->foo(); }}
    {
    }
    void work()
    {
        f();
    }
private:
    std::function<void()> f;
};

更多示例,请参见Codesandbox example

答案 3 :(得分:0)

我在下面如何检查所有选项:

JS 代码:

 const checkAll = (e) => {

  var value  = false

  if(e.target.checked){
    value = true;
  }
  
  Array.from(document.querySelectorAll("input[name="+name+"]"))
       .forEach((checkbox) => {
        document.getElementById(checkbox.id).checked = value;
       });
 }

HTML 代码(全选):

 <input type="checkbox" name="all" onChange={checkAll} />

HTML 代码(选项):

 <input type="checkbox" name={name} id={name+index} value={obj.id} />

选项是使用循环创建的,其中此类复选框的 id 是唯一的。