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:
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>
);