Hello I want to know how to apply "
I know the documentation is right there but I wasn't able to make it work this was my attempt and I would say I was close but clearly missing something very important
The idea is that when I click the "parent" one all of them get clicked, all of them changed to checked and all of them send the data to a variable and when I unclick they should remove it, and when I remove one in particular it should only remove that one in particular (that one is already working but idk if I have to add something else for the parent)
Individually they do what I want but I wanted to add the parent/main one so I can just check all of them:
This is my code:
//Functions
//set all students attempt
const [allStudentsID, setAllStudentsID] = useState();
const setAllStudents = () => {
setAllStudentsID(Array.isArray(estudiantes)?estudiantes.map(x=> x.label):[]);
console.log(allStudentsID)
}
//set individual one by one (works)
const [studentID, setStudentID] = useState([])
const setStudent = (estudiante) => {
if(!studentID.find(id => id === estudiante)){
setStudentID([ ... studentID, estudiante]);
}
else {
setStudentID(studentID.filter(studentId => studentId !== estudiante))
}
console.log(studentID)
}
Mapping/Render:
//Titles (not sure if I'm setting up correctly the checkbox)
<thead>
<tr className="Lista">
<th ><Checkbox
color = "primary"
id = "checkBox"
onChange = {() => setAllStudents()}
/>
</th>
<th>Nombre</th>
<th>Colegio</th>
<th>Grado</th>
<th>Accion</th>
</tr>
</thead>
//Table (this works)
{estudiantes.map((estudiantes, index) => (
<tr key={estudiantes.id || index}>
<td>
<Checkbox
checked={!!studentID.find( id => id === estudiantes.uid)}
color = "primary"
id = "checkBox"
onChange = {() => setStudent(estudiantes.uid, index)}
inputProps={{ 'aria-label': 'controlled' }}
/>
</td>
... some code that will finish the table
CodePudding user response:
As per your code and question, when you're using estudiantes.uid
to handle the checkboxes state, it works, but in setAllStudents
function, you're usingx.label
, which doesn't exist in the array, that's why your console log shows the undefined
. Maybe try updating the function to return the id
from the function.
const setAllStudents = () => {
setAllStudentsID(Array.isArray(estudiantes)?estudiantes.map(x=> x.id):[]);
console.log(allStudentsID)
}
CodePudding user response:
I encountered many problems using MUI.
I made this code for you, hope it helps:
import { Fragment, useState } from "react";
import Box from "@mui/material/Box";
import Checkbox from "@mui/material/Checkbox";
import { Card } from "@mui/material";
const estudiantes = [
{ uid: 1, label: "Student 1" },
{ uid: 2, label: "Student 2" },
{ uid: 3, label: "Student 3" }
];
const App = () => {
const [checkedStudents, setCheckedStudents] = useState([]);
const handleChange1 = (isChecked) => {
if (isChecked)
return setCheckedStudents(
estudiantes.map((estudiante) => estudiante.uid)
);
else setCheckedStudents([]);
};
const handleChange2 = (isChecked, uid) => {
const index = checkedStudents.indexOf(uid);
// The checked value is altered before the state changes for some reason is not a trully controlled component
// So the next conditions are INVERTED.
if (isChecked) return setCheckedStudents((state) => [...state, uid]);
if (!isChecked && index > -1)
return setCheckedStudents((state) => {
state.splice(index, 1);
return JSON.parse(JSON.stringify(state)); // Here's the trick => React does not update the f* state array changes even with the spread operator, the reference is still the same.
});
};
return (
<Fragment>
{/* Parent */}
<Checkbox
checked={checkedStudents.length === estudiantes.length}
indeterminate={
checkedStudents.length !== estudiantes.length &&
checkedStudents.length > 0
}
onChange={(event) => handleChange1(event.target.checked)}
/>
{/* Childrens */}
<Box sx={{ display: "flex", flexDirection: "column", ml: 3 }}>
{checkedStudents &&
estudiantes.map((estudiante) => (
<Checkbox
key={Math.random()}
checked={checkedStudents.includes(estudiante.uid)}
onChange={(event) =>
handleChange2(event.target.checked, estudiante.uid)
}
inputProps={{ "aria-label": "controlled" }}
/>
))}
</Box>
<h3>ID's: {JSON.stringify(checkedStudents)}</h3>
</Fragment>
);
};
export default App;