1

How to change checkbox value not only by clicking on that checkbox input but on the whole button that wraps input and span?

    const statuses = ["Draft", "Pending", "Paid"];

     const [checkedState, setCheckedState] = useState(
     new Array(statuses.length).fill(false)
    );

     const handleCheckboxChange = (position: number) => {
       const updatedCheckedState = checkedState.map((item, index) =>
         index === position ? !item : item
       );
       setCheckedState(updatedCheckedState);
     };

        {statuses.map((status, index) => (
              <button key={index}>
                <input
                  type="checkbox"
                  onChange={() => handleCheckboxChange(index)}
                />
                <span>{status}</span>
              </button>
            ))}
1
  • 1
    Replace the button with a label. Commented Sep 13, 2022 at 18:20

2 Answers 2

3

Move your handleCheckboxChange function to the button and use checked property to input for handling check-uncheck dynamically. As you see, in the checked property I give the value dynamically like this checked={checkedState[index]}.

import { useEffect, useState } from "react";
import "./styles.css";

export default function App() {
  const statuses = ["Draft", "Pending", "Paid"];

  const [checkedState, setCheckedState] = useState(
    new Array(statuses.length).fill(false)
  );

  const handleCheckboxChange = (position) => {
    const updatedCheckedState = checkedState.map((item, index) =>
      index === position ? !item : item
    );
    setCheckedState(updatedCheckedState);
  };

  return (
    <>
      {statuses.map((status, index) => (
        <button key={index} onClick={() => handleCheckboxChange(index)}>
          <input type="checkbox" checked={checkedState[index]} />
          <span>{status}</span>
        </button>
      ))}
    </>
  );
}

And another way is - just use label instead of button. In this case you need to give proper styles to the label.

  return (
    <>
      {statuses.map((status, index) => (
        <label key={index}>
          <input
            type="checkbox"
            onChange={() => handleCheckboxChange(index)}
            checked={checkedState[index]}
          />
          <span>{status}</span>
        </label>
      ))}
    </>
  );
Sign up to request clarification or add additional context in comments.

4 Comments

you're right. I forgot about checked props.
yeah, another way of doing this - use label instead of button
I think that in example with button there need to be an additional onChange event despite onClick on the wrapping button, because of the checked prop provided. If we dont do it the input remains uncontrolled and there are warnings in console.
To prevent the uncontrolled error you should add readOnly prop to your input.
0

You can just put the handler on the button instead of the input checkbox.
The reason is event in javascript will go from outer tag to inner tag. If you click on a button the event will fired in button before fired in button's children.
For details, see event bubbling and capturing

<button key={index} onClick={() => handleCheckboxChange(index)}>
                <input
                  type="checkbox"
                  //onChange={() => handleCheckboxChange(index)}
                  checked={checkedState[index]} 
                />
                <span>{status}</span>
              </button>

Comments

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.