Home > Back-end >  Get user roles input using checkboxes and save in an array using useState() in react
Get user roles input using checkboxes and save in an array using useState() in react

Time:04-11

I am creating an admin page where the admin can assign roles to other users. For this, I'm creating a front end input with checkboxes:

role options

Now based on the options that the admin selects on front end, i want to send the roles data to backend in form of an array:

roles: ['admin', 'seller']

useState should be able to add / remove items to this array based on whether the associated cell is checked or unchecked.

const [roles, setRoles] = useState([]);

const checkBoxInputs = [
{
  id: 1,
  label: 'Admin',
  value: 'admin',
},
{
  id: 2,
  label: 'Seller',
  value: 'seller',
},
{
  id: 3,
  label: 'User',
  value: 'user',
},
];

const [isChecked, setIsChecked] = useState(false);
const [roles, setRoles] = useState([]);

const handleCheckboxChange = (e) => {
  setIsChecked(!isChecked);
  if (isChecked) {
    setRoles([...roles, roles.push(e.target.value)]);
  } else {
    setRoles([roles.filter(e.target.value)]);
  }
};

console.log(values);
console.log(roles);

The app code:

<div>
   <div className="mb-2 pb-1 border-b text-sm">
      Choose user roles:
   </div>
<ul className="flex items-center gap-1">
{checkBoxInputs.map((role, index) => (
  <li key={index}>
    <input
      type="checkbox"
      id={role.value}
      name="roles"
      value={role.value}
      checked={isChecked}
      onChange={handleCheckboxChange}
    />
    <label htmlFor={role.value} className="text-sm ml-1">
      {role.label}
    </label>
  </li>
  ))}
</ul>
</div>

Though the current implementation either checks or unchecks all inputs together.

Also, the values don't get removed from roles array when the checkboxes are checked out.

CodePudding user response:

You should store the checked variable in each role:

const [roles, setRoles] = useState([]);

const checkBoxInputs = [
  {
    id: 1,
    label: "Admin",
    value: "admin",
    checked: false,
  },
  {
    id: 2,
    label: "Seller",
    value: "seller",
    checked: false,
  },
  {
    id: 3,
    label: "User",
    value: "user",
    checked: false,
  },
];

const [roles, setRoles] = useState([]);

const handleCheckboxChange = (e) => {
  const currentRole = roles.filter((r) => r.value === e.target.value);
  if (!currentRole) return; // Invalid role
  currentRole.checked = !currentRole.checked;
  if (currentRole.checked) {
    setRoles([...roles, roles.push(currentRole.value)]);
  } else {
    const otherRoles = roles.filter((r) => r.value !== currentRole.value);
    setRoles([...otherRoles]);
  }
  // Update original object
  checkBoxInputs.find(r => r.value === currentRole.value).checked = currentRole.checked
};

And then use that in your JSX

<div>
   <div className="mb-2 pb-1 border-b text-sm">
      Choose user roles:
   </div>
<ul className="flex items-center gap-1">
{checkBoxInputs.map((role, index) => (
  <li key={index}>
    <input
      type="checkbox"
      id={role.value}
      name="roles"
      value={role.value}
      checked={role.checked}
      onChange={handleCheckboxChange}
    />
    <label htmlFor={role.value} className="text-sm ml-1">
      {role.label}
    </label>
  </li>
  ))}
</ul>
</div>

CodePudding user response:

you should check in checked prop that checked value is equal to role.value.And also you should push data either using push() or spread operator.

const [roles, setRoles] = useState([]);

  const checkBoxInputs = [
    {
      id: 1,
      label: "Admin",
      value: "admin"
    },
    {
      id: 2,
      label: "Seller",
      value: "seller"
    },
    {
      id: 3,
      label: "User",
      value: "user"
    }
  ];

  const [CheckedValue, setCheckedValue] = useState();

  const handleCheckboxChange = (e) => {
    if (e.target.checked) {
      setCheckedValue(e.target.value);
      if (!roles.includes(e.target.value)) {
        setRoles([...roles, e.target.value]);
      }
    }
  };

then in return statement

return (
    <div>
      <div className="mb-2 pb-1 border-b text-sm">Choose user roles:</div>
      <ul className="flex items-center gap-1">
        {checkBoxInputs.map((role, index) => (
          <li key={index}>
            <input
              type="checkbox"
              id={role.value}
              name="roles"
              value={role.value}
              checked={role.value === CheckedValue}
              onChange={handleCheckboxChange}
            />
            <label htmlFor={role.value} className="text-sm ml-1">
              {role.label}
            </label>
          </li>
        ))}
      </ul>
    </div>
  );
  • Related