Home > Enterprise >  Next JS - Checkbox Select All
Next JS - Checkbox Select All

Time:04-28

I'm a beginner in Next Js. and I'm trying to implement select all on the checkboxes.

I following this reference https://www.freecodecamp.org/news/how-to-work-with-multiple-checkboxes-in-react/

what I expect is, if the checkbox select all is checked then sum all the prices.

but I don't know how to start it.

Here is my sandbox https://codesandbox.io/s/eager-feather-2ieme9

Any help with this would be greatly appreciated, been working on this for a while and exhausted all avenues!

CodePudding user response:

You can check the below logic with some explanation

You also can check this sandbox for the test

import { useState } from "react";
import { toppings } from "./utils/toppings";
// import InputTopings from "./InputTopings";
const getFormattedPrice = (price) => `$${price.toFixed(2)}`;

export default function TopingApp() {
  const [checkedState, setCheckedState] = useState(
    new Array(toppings.length).fill(false)
  );

  // console.log(checkedState);
  const [total, setTotal] = useState(0);

  //Separate `updateTotal` logic for avoiding duplication
  const updateTotal = (checkboxValues) => {
    const totalPrice = checkboxValues.reduce((sum, currentState, index) => {
      if (currentState === true) {
        return sum   toppings[index].price;
      }
      return sum;
    }, 0);

    setTotal(totalPrice);
  };

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

    setCheckedState(updatedCheckedState);
    //update total
    updateTotal(updatedCheckedState);
  };

  const handleSelectAll = (event) => {
    //filled all checkboxes' states with `Check All` value
    const updatedCheckedState = new Array(toppings.length).fill(
      event.target.checked
    );

    setCheckedState(updatedCheckedState);
    //update total
    updateTotal(updatedCheckedState);
  };

  return (
    <div className="App">
      <h3>Select Toppings</h3>
      <div className="call">
        <input
          type="checkbox"
          name="checkall"
          checked={checkedState.every((value) => value)}
          onChange={handleSelectAll}
        />
        <label htmlFor="checkall">Check All</label>
      </div>
      <ul className="toppings-list">
        {toppings.map(({ name, price }, index) => {
          return (
            <li key={index}>
              <div className="toppings-list-item">
                <div className="left-section">
                  <input
                    type="checkbox"
                    // id={`custom-checkbox-${index}`}
                    name={name}
                    value={name}
                    checked={checkedState[index]}
                    onChange={() => handleOnChange(index)}
                  />
                  <label>{name}</label>
                </div>
                <div className="right-section">{getFormattedPrice(price)}</div>
              </div>
            </li>
          );
        })}
        <li>
          <div className="toppings-list-item">
            <div className="left-section">Total:</div>
            <div className="right-section">{getFormattedPrice(total)}</div>
          </div>
        </li>
      </ul>
    </div>
  );
}

CodePudding user response:

You can lift the 'Check all' state to a parent object and on change of this state set all <input/> tags value to that state you can achieve this by dividing your app. First create a component for the items in the list like <Toppings/> and give props to this component like so <Toppings name={name} price={price} checkAll={checkAll}/> inside the toppings component create a state variable like this

const Toppings = ({name,price, checkAll}) => {
    const [checked,setChecked] = useState(checkAll)
    return (
       <li key={index}>
          <div className="toppings-list-item">
            <div className="left-section">
              <input
                type="checkbox"
                // id={`custom-checkbox-${index}`}
                name={name}
                value={checked}
                onChange={setChecked(!checked)}
              />
              <label>{name}</label>
            </div>
          </div>
        </li>
     )
}

Edit:

inside index.js:

const [checkAll, setCheckAll] = useState(false)


//when rendering inside return method 
 {toppings.map(({name,price},index) => <Toppings key={index} name={name} price={price} checkAll={checkAll}/> ) 
  • Related