6

I want to display the selected checkbox items, for which I'm using material-ui checkbox.

Right now I'm only able to display the items with checkboxes, but I am not able to display the selected items.

I know it is easy but I'm new to reactjs and redux so finding it difficult to start.

Hoping for a help.

Thank you.

this.state = {
            data: [apple, kiwi, banana, lime, orange, grape],
        }}
    handleCheck(x) {
        this.state.checkedValues.push(x);
    }
render(){
       {this.state.data.map((x) =>
             <Checkbox
               label={x} key={x.toString()}
               onCheck={() => this.handleCheck(x)}
               checked=true
              }/>
          )}}
2
  • I have answered this question here. I hope it helps. :) Commented Jan 28, 2019 at 13:54
  • Kindly accept the answer so that people visiting here get to know the solution quickly Commented Feb 19, 2019 at 10:28

6 Answers 6

8

Modifying the answer by @BravoZulu by adding the event as the argument in onChange() function.(Also note that use onChange() instead of onCheck() for material-UI checkboxes as shown in the official documentation). Also, don't forget to bind the function in the constructor. I hope this helps the community. Below is the code.

    class App extends Component {
    constructor(props) {
        this.handleCheck = this.handleCheck.bind(this);
        super(props);
        this.state = {
        data: [apple, kiwi, banana, lime, orange, grape],
        checkedValues: []
        }
    }
    handleCheck(e,x) {
        this.setState(state => ({
        checkedValues: state.checkedValues.includes(x)
            ? state.checkedValues.filter(c => c !== x)
            : [...state.checkedValues, x]
        }));
    }

    render() {
        return (<div>
        { this.state.data.map(x =>
            <Checkbox
            label={x} key={x.toString()}
            onChange={e => this.handleCheck(e,x)}
            checked={this.state.checkedValues.includes(x)}
            />
        )}}
        </div>)
    }
}
Sign up to request clarification or add additional context in comments.

Comments

3

In the handleCheck function, you are attempting to update your component state incorrectly. You need to use setState to make changes to state. In your example, state isn't getting updated so that is probably why you aren't seeing anything get selected. Also, gonna help clean up your example a bit:

class CheckboxList extends React.Component{
  constructor() {
    super();
    this.state = {
        data: ['apple', 'kiwi', 'banana', 'lime', 'orange', 'grape'],
      checkedValues: []
    }
  }
  handleCheck(index) {
    this.setState({
        checkedValues: this.state.checkedValues.concat([index])
    });
    console.log(this.state.checkedValues.concat([index]))
  }
  render(){
   const checks = this.state.data.map( (item, index) => {
         return (
         <span key={item}>
            <input type="checkbox"
           value={item}
           onChange={this.handleCheck.bind(this, index)} //Use .bind to pass params to functions
           checked={this.state.checkedValues.some( selected_index => index === selected_index )}
          />
          <label>{item}</label>
         </span>)
   });
   return <div>{checks}</div>
  }
}

Update: Added working jsfiddle.

10 Comments

He won't be able to uncheck checkboxes, only check new ones
Yeah I kind of gave up on trying to figure out what they were trying to do based on their example. Hopefully this is enough to point them in the right direction.
Wow, okay I guess I'll actually try to get you something that works. Updated my answer. Let me know if you have questions or want to know why/what is going on.
checked={this.state.checkedValues.some( selected_index => index === selected_index )} what is happening in this line??
Updated jsfiddle to handle unselecting as well: jsfiddle.net/jwm6k66c/2920
|
3

A bit late to the party but here's a solution using a functional component and hooks

import React, { useState } from 'react';
import Checkbox from '@material-ui/core/Checkbox';

const App = ({ data }) => {
  const [checked, setChecked] = useState([]);

  const handleCheck = (event) => {
    const { value } = event.target;
    setChecked(checked.includes(value) ? checked.filter(c => c !== value) : [...checked, value]);
  };

  return (
    <div>
      {data.map(({ value }) => (
         <Checkbox onChange={e => handleCheck(e)} checked {checked.includes(value)} />
      ))}
   </div>
  );
};

export default App;

2 Comments

Hi, This solution is worked perfectly for me. Just one mistake there is that you need to put an equal to sign (=) after checked in the <Checkbox Component. Anyway thanks for this.
How to pass the checked value to parent component? When I pass, I am one step behind in state.
2

In React, you shouldn't push data directly to your state. Instead, use the setState function.

class App extends Component {
  constructor(props) {
    super(props);
    this.state = {
      data: [apple, kiwi, banana, lime, orange, grape],
      checkedValues: []
    }
  }
  handleCheck(x) {
    this.setState(state => ({
      checkedValues: state.checkedValues.includes(x)
        ? state.checkedValues.filter(c => c !== x)
        : [...state.checkedValues, x]
    }));
  }

  render() {
    return (<div>
    { this.state.data.map(x =>
        <Checkbox
          label={x} key={x.toString()}
          onCheck={() => this.handleCheck(x)}
          checked={this.state.checkedValues.includes(x)}
         />
    )}}
    </div>)
  }
}

7 Comments

You don't have to copy state each time you do setState, you're allowed to just update one piece of state at a time.
@ChaseDeAnda It's true, I edited so I just return the updated part of the state
@devanya If you downvote the answer, at least tell me what's wrong with it.
But what errors are you getting? I tested this code and it works
Arrow functions don’t define their own context so ‘this’ is set to the enclosing context, so you don't need to bind. includes over some is insignificant in terms of performance and a matter of preference, not best practices.
|
0

I was also stuck on this issue for quite some time when I finally found a fix to this. It never works for a functional component which returns a check box. I made a separate class component and wrapped it in Redux Field component and it worked perfectly. I really never understood why it didn't work for the fucntional component as it what is shown in their official example.

I have written the code that worked for me. Hope it helps :)

class CheckBoxInput extends React.Component {

  onCheckBoxSelectChange = (input) => 
  {
    input.onChange();
    this.props.onSelectChange();
  }

  render() {
    const { label, input,} = this.props;
    let name = input.name;

    return (
      <div>
        <InputLabel htmlFor={label} style={{paddingTop: '15px'}}> {label} </InputLabel>
         <FormControl {...input} >
          <Checkbox
            name = {name}
            label = {label}
            color= "primary"
            checked={input.value ? true : false}
            onChange={() => this.onCheckBoxSelectChange(input)}
          />          
        </FormControl>
      </div>

    )
  }
}

const CheckBox = (props) => <Field component={CheckBoxInput} {...props} />;
export default CheckBox;

And to use this checkbox component:

 <CheckBox  name="isCurrent" label="Current" onSelectChange = {this.toggleCurrentEmployerSelection} />

Comments

-1

In case you are working with objects instead of simple data types, here is a working approache:

class App extends Component {
  constructor(props) {
    super(props);
    this.state = {
      data: [{id: 1, name:'banana'},
             {id: 2, name:'kiwi'}],
      checkedValues: []
    }
  }
  handleCheck(element) {
     const values = this.state.checkedValues.filter(e => e.id === element.id).length > 0
            ? this.state.checkedValues.splice( this.state.checkedValues.findIndex( e => e.id === element.id),1)
            : this.state.checkedValues.push(element);
     this.setState({
         checkedValues: values
     });
  }

  render() {
    return (<div>
    { this.state.data.map(el =>
        <Checkbox
           checked={this.state.checkedValues.filter(e => e.id === el.id).length > 0}
           onChange={this.handleCheck.bind(this, el)} //Use .bind to pass params to functions
           value={el}
        />
    )}}
    </div>)
  }
}

So basically what the function handleCheck does is it checks whether the selected object is in the checkedValues array, if that is the case then it deletes it (case uncheck), otherwise it adds it (case check), is i add the checked object to the checkedValues array.

in the Checkbox checked checks whether there is an object in the checkedValues array that is equal to the current loop object, (case checked/unchecked)

1 Comment

Uncaught TypeError: _this2.state.checkedValues.filter is not a function

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.