Jose Alarcon
Jose Alarcon

Reputation: 21

React Redux - select all checkbox

I have been searching on Google all day to try and find a way to solve my issue. I've created a "product selection page" and I'm trying to add a "select all" checkbox that will select any number of products that are displayed (this will vary depending on the customer). It's coming along and I've got all the checkboxes working but I can't get "select all" to work. Admittedly I'm using some in-house libraries and I think that's what's giving me trouble as I'm unable to find examples that look like what I've done so far. OK, so the code to create my checkboxGroup is here:

    let productSelectionList = (
      <FormGroup className="productInfo">
        <Field
          component={CheckboxGroup}
          name="checkboxField"
          vertical={true}
          choices={this.createProductList()}
          onChange={this.handleCheckboxClick}
          helpText="Select all that apply."
          label="Which accounts should use this new mailing address?"
        />
      </FormGroup>
    );

As you can see, my choices will be created in the createProductList method. That looks like this:

createProductList() {
    const { products } = this.props;
    const selectAllCheckbox = <b>Select All Accounts</b>;
    let productList = [];
    productList.push({ label: selectAllCheckbox, value: "selectAll" });
    if (products && products.length > 0) {
      products.forEach((product, idx) => {
        productList.push({
          label: product.productDescription,
          value: product.displayArrangementId
        });
      });
    }
    return productList;
  }

Also note that here I've also created the "Select All Accounts" entry and then pushed it onto the list with a value of "selectAll". The actual products are then pushed on, each having a label and a value (although only the label is displayed. The end result looks like this: Select Products checkboxes I've managed to isolate the "select all" checkbox with this function:

  handleCheckboxClick(event) {
    // var items = this.state.items.slice();
    if (event.selectAll) {
        this.setState({
          'isSelectAllClicked': true
        });
    } else {
        this.setState({
          'isSelectAllClicked': false
        });
    }
  }

I also created this componentDidUpdate function:

componentDidUpdate(prevProps, prevState) {
  if (this.state.isSelectAllClicked !== prevState.isSelectAllClicked && this.state.isSelectAllClicked){

    console.log("if this ", this.state.isSelectAllClicked);
    console.log("if this ", this.props);
  } else if (this.state.isSelectAllClicked !== prevState.isSelectAllClicked && !this.state.isSelectAllClicked){
    console.log("else this ", this.state.isSelectAllClicked);
    console.log("else this ", this.props);
  }
}

So in the console, I'm able to see that when the "select all" checkbox is clicked, I do get a "True" flag, and unclicking it I get a "False". But now how can I select the remaining boxes (I will admit that I am EXTREMELY new to React/Redux and that I don't have any previous checkboxes experience). In Chrome, I'm able to see my this.props as shown here.. this.props

You can see that this.props.productList.values.checkboxField shows the values of true for the "select all" checkbox as well as for four of the products. But that's because I manually checked off those four products for this test member that has 14 products. How can I get "check all" to select all 14 products? Did I go about this the wrong way? (please tell me that this is still doable) :(

Upvotes: 2

Views: 3543

Answers (2)

Alexej
Alexej

Reputation: 630

There is a package grouped-checkboxes which can solve this problem.

In your case you could map over your products like this:

import React from 'react';
import {
  CheckboxGroup,
  AllCheckerCheckbox,
  Checkbox
} from "@createnl/grouped-checkboxes";

const App = (props) => {
  const { products } = props

  return (
    <CheckboxGroup onChange={console.log}>
      <label>
        <AllCheckerCheckbox />
        Select all accounts
      </label>
      {products.map(product => (
        <label>
          <Checkbox id={product.value} />
          {product.label}
        </label>
      ))}
    </CheckboxGroup>
  )
}

More examples see https://codesandbox.io/s/grouped-checkboxes-v5sww

Upvotes: 0

Chaim Friedman
Chaim Friedman

Reputation: 6253

My guess is your single product checkboxes are bound to some data you have in state, whether local or redux. The checkbox input type has a checked prop which accepts a boolean value which will determine if the checkbox is checked or not.

The idea would be to set all items checked prop (whatever you are actually using for that value) to true upon clicking the select all checkbox. Here is example code you can try and run.

import React, { Component } from 'react';
import './App.css';

class App extends Component {
  state = {
    items: [
      {
        label: "first",
        checked: false,
      },
      {
        label: "last",
        checked: false,
      }
    ],
    selectAll: false,
  }

  renderCheckbooks = (item) => {
    return (
      <div key={item.label}>
        <span>{item.label}</span>
        <input type="checkbox" checked={item.checked} />
      </div>
    );
  }

  selectAll = (e) => {
    if (this.state.selectAll) {
      this.setState({ selectAll: false }, () => {
        let items = [...this.state.items];
        items = items.map(item => {
          return {
            ...item,
            checked: false,
          }
        })
        this.setState({ items })
      });
    } else {
      this.setState({ selectAll: true }, () => {
        let items = [...this.state.items];
        items = items.map(item => {
          return {
            ...item,
            checked: true,
          }
        })
        this.setState({ items })
      });
    }
  }

  render() {
    return (
      <div className="App">
        {this.state.items.map(this.renderCheckbooks)}
        <span>Select all</span>
        <input onClick={this.selectAll} type="checkbox" checked={this.state.selectAll} />
      </div>
    );
  }
}

export default App;

I have items in state. Each item has a checked prop which I pass to the checkbox getting rendered for that item. If the prop is true, the checkbox will be checked otherwise it wont be. When I click on select all, I map thru my items to make each one checked so that the checkbox gets checked.

Here is a link to a codesandbox where you can see this in action and mess with the code.

Upvotes: 1

Related Questions