JJ36
JJ36

Reputation: 169

React js select all checkboxes not in react table

In what way I can check/uncheck all checkboxes if in the set of data there is any boolean field and I'm not using react-table? For single checkbox is working but not for all. Thank you for any tip. I named checkboxes as corresponding name of the data in the table but it is not working.

This is my class:

class Boxes extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            datas: [
                {name: "name1", status: 1},
                {name: "name3", status: 0},
                {name: "name2", status: 2},
            ],
            checkboxes: [],
            selectAll: true,
        };
        this.toggleAllChange = this.toggleAllChange.bind(this);
        this.toggleOneChange = this.toggleOneChange.bind(this);
    }

  toggleAllChange(event) {
    let checked = event.target.checked;
    console.log(checked);

    this.setState({
      checkAll: checked,
      checkboxes: document.getElementsByClassName("chbx")
    });

    for (let i in this.state.checkboxes){
      let nameAct = this.state.checkboxes.item(i).name;
      let checkbox = document.getElementsByName(nameAct);
      this.setState({
         [nameAct]: checked
      });
    }
  }

toggleOneChange(event) {
    const target = event.target;
    const value = target.checked;
    const name = target.name;

    this.setState({
      [name]: value
    });
}

And my Table in render method:

<div className="input-group mb-3">
    <InputGroup className="mb-3">
        <input
            type="checkbox"
            value="checkAll"
            defaultChecked={this.state.selectAll}
            onChange={this.toggleAllChange.bind(this)}/>
        Check/Uncheck All
    </InputGroup>
</div>
<Table responsive>
    <thead className="text-primary">
    <tr>
        <th>Data name</th>
        <th>Data status</th>
        <th>Check</th>
    </tr>
    </thead>
    <tbody>
    {this.state.datas.map(data => (
        <tr>
            <td>{data.name}</td>
            <td>{data.status}</td>
            <td>
                <input
                    className="chbx"
                    type="checkbox"
                    id={"chbx" + data.name}
                    name={"chbx" + data.name}
                    defaultChecked={this.state.selectAll}
                    onChange={this.toggleOneChange.bind(this)}
                />
            </td>
        </tr>
    ))}
    </tbody>
</Table>

Upvotes: 3

Views: 1837

Answers (1)

Fraction
Fraction

Reputation: 12993

Look at the following example, I've:

  • Used an object checkBoxObj to manage the state of checkboxes
  • Used the checked attribute instead of defaultChecked and checkBoxObj:
<input
  className="chbx"
  type="checkbox"
  id={"chbx" + data.name}
  name={"chbx" + data.name}
  checked={this.state.checkBoxObj["chbx" + data.name]}
  onChange={this.toggleOneChange.bind(this)}
/>

  • Change toggleAllChange and toggleOneChange methods

Live example:

const datas = [
    {name: "name1", status: 1},
    {name: "name3", status: 3},
    {name: "name2", status: 2},
];
const selectAll = true;
const checkBoxObj = datas.reduce((acc, d) => (acc["chbx" + d.name] = selectAll, acc), {});

class Boxes extends React.Component {
  constructor(props) {
      super(props);
      this.state = {
          datas,
          //allChecked: true,
          selectAll,
          checkBoxObj,
      };
      this.toggleAllChange = this.toggleAllChange.bind(this);
      this.toggleOneChange = this.toggleOneChange.bind(this);
  }

  toggleAllChange(event) {
      const selectAll = event.target.checked;
      
      const newCheckBoxObj = {};
      for(let k in this.state.checkBoxObj) {
        newCheckBoxObj[k] = selectAll;
      }

      this.setState({
          checkBoxObj: newCheckBoxObj,
          selectAll
      });
  }

  toggleOneChange(event) {
      const target = event.target;
      const value = target.checked;
      const name = target.name;
      
      const newCheckBoxObj = { ...this.state.checkBoxObj, [name]: value };
      
      const selectAll = Object.values(newCheckBoxObj).every(chk => chk);
      
  
      this.setState({
        checkBoxObj: newCheckBoxObj,
        selectAll
      });
  }
  
  render() {
    const filteredDatas = this.state.datas;
    return (
      <div>
        <div className="input-group mb-3">
                <input
                    type="checkbox"
                    value="checkAll"
                    style={{ marginRight: 5 }}
                    checked={this.state.selectAll}
                    onChange={this.toggleAllChange.bind(this)}
                />{" "}
                Check/Uncheck All
        </div>
        <table responsive>
            <thead className="text-primary">
            <tr>
                <th>Data name</th>
                <th>Data status</th>
                <th>Check</th>
            </tr>
            </thead>
            <tbody>
            {filteredDatas.map(data => (
                <tr>
                    <td>{data.name}</td>
                    <td>{data.status}</td>
                    <td>
                        <input
                            className="chbx"
                            type="checkbox"
                            id={"chbx" + data.name}
                            name={"chbx" + data.name}
                            checked={this.state.checkBoxObj["chbx" + data.name]}
                            onChange={this.toggleOneChange.bind(this)}
                        />
                    </td>
                </tr>
            ))}
            </tbody>
        </table>
      </div>)
  }

}

ReactDOM.render(<Boxes />, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="root"></div>

Upvotes: 1

Related Questions