I have a material-ui Table
and have been implementing multi-select functionality on it.
My multi select should behave as follows:
TableHead
will select / deselect all rows in the Table
when toggled. Each row has its own individual unique id
.
I maintain a Set
called idsOfSelectedRows
via a useState
hook to keep track of all rows currently selected.
Each TableRow
has a Checkbox
which looks like this
<Checkbox
className={
idsOfSelectedRows.size === 0 &&
styles.rowSelectionCheckboxStyle
}
onChange={() => handleRowSelectionCheckboxClick}
checked={idsOfSelectedRows.has(row.id)}
/>
and handleRowSelectionCheckboxClick
looks like this
const handleRowSelectionCheckboxClick = event => {
const idOfClickedRow = event.target.attributes.getNamedItem("id").value;
//If the checkbox has just become checked then add it to the idOfSelectedRows Set, otherwise remove it.
setIdsOfSelectedRows(
event.target.checked
? new Set(idsOfSelectedRows.add(String(idOfClickedRow)))
: () => {
idsOfSelectedRows.delete(String(idOfClickedRow));
return new Set(idsOfSelectedRows);
}
);
};
My issue is that clicking on the checkboxes on the rows is unresponsive. I can select them all by clicking on the select all Checkbox
in the TableHead
but clicking on checkboxes in individual rows does not change their state?
Here's a full CodeSandbox reproducing the exact issue. What do I need to do to make the checkboxes in the rows be toggleable?
Remove the () =>
from the onChange
assignment for a quick fix.
Why
You're declaring an anonymous inline function, but that function does not call anything (missing ()
that is syntax to call a function). onChange
accepts a function reference. When you give it an inline function, that's the function it will call. The other option is to only pass it the function reference of handleRowSelectionCheckboxClick
, and then that function will be called on change instead of the anonymous function middleman.
So your two options are:
onChange={handleRowSelectionCheckboxClick} // Just the reference
OR
onChange={(e) => handleRowSelectionCheckboxClick(e)} // New inline function that calls your function
The second way is unnecessary in most cases. The first is preferred unless you need to pass custom parameters. Here is an example of how it might be useful:
onChange={(e) => handleRowSelectionCheckboxClick(e, id)}
In your sandbox, you map over elements and each gets a change handler. To treat them separately in the handler, you can pass an extra variable to the function like above.
For example, I got your sandbox working by changing the handler and assignment to this:
const handleRowSelectionCheckboxClick = (event, idOfClickedRow) => {
...
onChange={(e) => handleRowSelectionCheckboxClick(e, row.id)}
This line: event.target.attributes.getNamedItem("id").value;
won't give you the required id, since there isn't one passed, change the chekbox
like so:
<Checkbox
id={row.id}
onChange={handleRowSelectionCheckboxClick}
checked={idsOfSelectedRows.has(row.id)}
/>
Then, retreive the ID like so:
const idOfClickedRow = event.target.attributes.id.value;
handleRowSelectionCheckboxClick
function call like shown in the example.
If you like your solution with an anonymous function, you should add the ()
: onChange={() => handleRowSelectionCheckboxClick()}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.