React input checkbox select all component

后端 未结 3 1809
野的像风
野的像风 2021-01-02 16:19

I\'m trying to build a proper react input checkbox select all component. The idea is that there is a component and

相关标签:
3条回答
  • 2021-01-02 17:07

    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.

    1. CheckBox - Reusable Component
    2. CheckBoxList - Reusable Component
    3. CityList - End level where you can create states list or any list by cloning this.

    Stack Blitz with Module - 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>

    0 讨论(0)
  • 2021-01-02 17:14

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

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

    Instead, the checkbox should be implemented as an item that is simply either checked or 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 checked status of each of your checkboxes:

      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.checked array. When the <Inputcheckbox> changes, we bind an index to the change handler, so we know which array element to modify.

      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 All checkbox is checked, we simply set every element of this.state.checked to 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/

    0 讨论(0)
  • 2021-01-02 17:16

    There is a simple package that solves this problem 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

    0 讨论(0)
提交回复
热议问题