2

Hello how can I handle onChange for multiple check box? The following example allows me to control the value of one checkbox.

class App extends Component {
  constructor() {
    super();
    this.state = {
      i_agree: false
    };
    this.handleChange = this.handleChange.bind(this);
    this.handleSubmit = this.handleSubmit.bind(this);
  }
     
  handleChange(event) {
    this.setState({i_agree: !this.state.i_agree});
  }
     
  handleSubmit(event) {
    console.log(this.state);
    event.preventDefault();
  }
     
  render() {
    return (
      <div>
        <h1>React Checkbox onChange Example - ItSolutionStuff.com</h1>
        <form onSubmit={this.handleSubmit}>
           
          <label>
            <input
              type="checkbox"
              defaultChecked={this.state.i_agree}
              onChange={this.handleChange}
            /> I Agree with this content...
          </label>
         <label>
            <input
              type="checkbox"
              defaultChecked={this.state.isChecked}
              onChange={this.handleChange}
            /> I want to control this...
          </label>
           
          <input type="submit" value="Submit" />
        </form>
      </div>
    );
  }
}

How can I set my handleChange function to handle changes for each checkbox instead of checking for one.

Reference Link

Attempt 1

class App extends Component {
      constructor() {
        super();
        this.state = {
          i_agree: false,
          isChecked: false

        };
        this.handleChange = this.handleChange.bind(this);
        this.handleSubmit = this.handleSubmit.bind(this);
      }
         
      handleChange(event) {
        this.setState({
          [e.target.name]: !e.target.value
        });
      }
         
      handleSubmit(event) {
        console.log(this.state);
        event.preventDefault();
      }
         
      render() {
        return (
          <div>
            <h1>React Checkbox onChange Example - ItSolutionStuff.com</h1>
            <form onSubmit={this.handleSubmit}>
               
              <label>
                <input
                  type="checkbox"
                  defaultChecked={this.state.i_agree}
                  onChange={this.handleChange}
                  name="i_agree"
                /> I Agree with this content...
              </label>
             <label>
                <input
                  type="checkbox"
                  defaultChecked={this.state.isChecked}
                  onChange={this.handleChange}
                  name="isChecked"
                /> I want to control this...
              </label>
               
              <input type="submit" value="Submit" />
            </form>
          </div>
        );
      }
    }

I Updated the onChange handler and added name attributes in each label. But this did not work or threw any errors.

1 Answer 1

4

I would use checked instead of defaultChecked to have a controlled checkbox input.

for handleChange you can use name and checked attributes to update checkbox state (you could also do a flip on its boolean state instead of using checked). this way you can have only one handler for all your checkboxes.

Typescript solution

import React from "react";

interface CheckboxProps {
  checked: boolean;
  label: string;
  name: string;
  onChange: (e: React.ChangeEvent<HTMLInputElement>) => void;
}
// I abstracted Checkbox to a component but it's up to you
const Checkbox = ({ checked, onChange, label, name }: CheckboxProps) => (
  <label>
    <input
      type="checkbox"
      checked={checked} // use checked to have a controlled component
      onChange={onChange}
      name={name}
    />
    {label}
  </label>
);

interface AppState {
  iAgree: boolean;
  wantCookies: boolean;
  wishList: boolean;
}

class App extends React.Component<{}, AppState> {
  // constructor method is called implicit you can define state outside
  // for binding methods, you can declare them as arrow functions
  state = {
    iAgree: false,
    wantCookies: false,
    wishList: false
  };

  // extract name and checked properties
  handleChange = ({
    target: { name, checked }
  }: React.ChangeEvent<HTMLInputElement>) =>
    this.setState({ [name]: checked } as Pick<AppState, keyof AppState>);

  handleSubmit = (event: React.FormEvent<HTMLFormElement>) => {
    console.log(this.state);
    event.preventDefault();
  };

  render() {
    const { iAgree, wantCookies, wishList } = this.state;
    return (
      <div>
        <h1>React Checkbox onChange Example - ItSolutionStuff.com</h1>
        <form onSubmit={this.handleSubmit}>
          <Checkbox
            onChange={this.handleChange}
            name={"iAgree"}
            checked={iAgree}
            label={"I agree with terms"}
          />
          <Checkbox
            onChange={this.handleChange}
            name={"wantCookies"}
            checked={wantCookies}
            label={"I want more cookies"}
          />
          <Checkbox
            onChange={this.handleChange}
            name={"wishList"}
            checked={wishList}
            label={"Put Me on wishlist"}
          />
          <br />
          <input type="submit" value="Submit" />
        </form>
      </div>
    );
  }
}

export default App;

Javascript solution

import React from "react";

// I abstracted Checkbox to a component but it's up to you
const Checkbox = ({ checked, onChange, label, name }) => (
  <label>
    <input
      type="checkbox"
      checked={checked} // use checked to have a controlled component
      onChange={onChange}
      name={name}
    /> { label }
  </label>
)

class App extends React.Component {
    // constructor method is called implicit you can define state outside
    // for binding methods, you can declare them as arrow functions
    state = {
      iAgree: false,
      wantCookies: false,
      wishList: false,
    };

  // extract name and checked properties
  handleChange = ({target: { name, checked }}) => this.setState({[name]: checked});
  
  handleSubmit= (event) => {
    console.log(this.state);
    event.preventDefault();
  }
     
  render() {
    const { iAgree, wantCookies, wishList } = this.state
    return (
      <div>
        <h1>React Checkbox onChange Example - ItSolutionStuff.com</h1>
        <form onSubmit={this.handleSubmit}>
          <Checkbox onChange={this.handleChange} name={'iAgree'} checked={iAgree} label={'I agree with terms'} />
          <Checkbox onChange={this.handleChange} name={'wantCookies'} checked={wantCookies} label={'I want more cookies'} />
          <Checkbox onChange={this.handleChange} name={'wishList'} checked={wishList} label={'Put Me on wishlist'} />
          <br/>
          <input type="submit" value="Submit" />
        </form>
      </div>
    );
  }
}

export default  App

fwiw I removed the constructor since it's not necessary. You can keep it though, it's only a cleaner way to declare your classes.

sandbox with implementation TS: https://codesandbox.io/s/so-multi-checkboxes-ts-qz20m

sandbox with implementation JS: https://stackblitz.com/edit/so-multi-checkboxes?file=src/App.js

Sign up to request clarification or add additional context in comments.

7 Comments

This is what I am looking for, however handleChange function you have here is not working for me.
added a sandbox with code implementation to help you out. you can check it out to find if there's any difference.
I appreciate your help! This is it!
When I tried to add the const CheckBox I am seeing this syntax error: var checked: any Binding element 'checked' implicitly has an 'any' type.ts(7031) for --> ({ checked, onChange, label, name }
this is related to typescript, I didn't notice you were using ts at your code. you need to add an interface to declare the props type. here you have a similar issue that might solve it stackoverflow.com/questions/55370851/…
|

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.