I am using the material-ui data table for sorting. This incorporates a checkbox on each row. I have made it that each row returns a click through to a link.
However, I don't want the checkbox to act as a click though and want it to behave as a checkbox and add the row to selected. But when clicking the checkbox the row link is returned.
I need to exclude that cell from the row link or someway to exclude the checkbox.
https://codesandbox.io/s/rlkv87vor4
This is what I have tried for the logic:
Click handler
if (event.target.classList.contains('selectCheckbox')) {
return console.log('checkbox select');
} else {
return console.log('row link');
}
In my demo row link
is always being returned when clicking the checkbox.
<TableCell padding="checkbox">
<Checkbox className="selectCheckbox" checked={isSelected} />
</TableCell>
The most straightforward way to deal with this is to have two separate handleClick
methods for the checkbox and the row (e.g. handleCheckboxClick
and handleRowClick
).
In handleCheckboxClick
you can then call event.stopPropagation();
in order to prevent handleRowClick
from being called.
So the following portions of EnhancedTable
would change from:
handleClick = (event, id) => {
if (event.target.classList.contains("selectCheckbox")) {
console.log("checkbox select");
} else {
console.log("row link");
}
const { selected } = this.state;
const selectedIndex = selected.indexOf(id);
let newSelected = [];
if (selectedIndex === -1) {
newSelected = newSelected.concat(selected, id);
} else if (selectedIndex === 0) {
newSelected = newSelected.concat(selected.slice(1));
} else if (selectedIndex === selected.length - 1) {
newSelected = newSelected.concat(selected.slice(0, -1));
} else if (selectedIndex > 0) {
newSelected = newSelected.concat(
selected.slice(0, selectedIndex),
selected.slice(selectedIndex + 1)
);
}
this.setState({ selected: newSelected });
};
...
<TableRow
hover
onClick={event => this.handleClick(event, n.id)}
role="checkbox"
aria-checked={isSelected}
tabIndex={-1}
key={n.id}
selected={isSelected}
>
<TableCell className="selectCheckbox" padding="checkbox">
<Checkbox
onClick={event => this.handleClick(event, n.id)}
className="selectCheckbox"
checked={isSelected}
/>
</TableCell>
to something like the following:
handleCheckboxClick = (event, id) => {
event.stopPropagation();
console.log("checkbox select");
const { selected } = this.state;
const selectedIndex = selected.indexOf(id);
let newSelected = [];
if (selectedIndex === -1) {
newSelected = newSelected.concat(selected, id);
} else if (selectedIndex === 0) {
newSelected = newSelected.concat(selected.slice(1));
} else if (selectedIndex === selected.length - 1) {
newSelected = newSelected.concat(selected.slice(0, -1));
} else if (selectedIndex > 0) {
newSelected = newSelected.concat(
selected.slice(0, selectedIndex),
selected.slice(selectedIndex + 1)
);
}
this.setState({ selected: newSelected });
};
handleRowClick = (event, id) => {
console.log("row link");
};
...
<TableRow
hover
onClick={event => this.handleRowClick(event, n.id)}
role="checkbox"
aria-checked={isSelected}
tabIndex={-1}
key={n.id}
selected={isSelected}
>
<TableCell className="selectCheckbox" padding="checkbox">
<Checkbox
onClick={event =>
this.handleCheckboxClick(event, n.id)
}
className="selectCheckbox"
checked={isSelected}
/>
Here's a CodeSandbox showing this approach:
Simply add onClick on the checkbox and call e.stopPropagation();
to prevent call onClick twice from the checkbox and from the row component !
handleClick = (event, id) => {
event.stopPropagation();
const {selected} = this.state;
const selectedIndex = selected.indexOf(id);
let newSelected = [];
if (selectedIndex === -1) {
newSelected = newSelected.concat(selected, id);
} else if (selectedIndex === 0) {
newSelected = newSelected.concat(selected.slice(1));
} else if (selectedIndex === selected.length - 1) {
newSelected = newSelected.concat(selected.slice(0, -1));
} else if (selectedIndex > 0) {
newSelected = newSelected.concat(
selected.slice(0, selectedIndex),
selected.slice(selectedIndex + 1),
);
}
this.setState({selected: newSelected});
};
<TableRow
hover
onKeyDown={event => this.handleKeyDown(event, n.id)}
role="checkbox"
aria-checked={isSelected}
tabIndex={-1}
key={n.id}
onClick={event => onMore(event, n.id)}
selected={isSelected}
>
<TableCell padding="checkbox">
<Checkbox color="primary" checked={isSelected}
onClick={event => this.handleClick(event, n.id)}/>
</TableCell>
</TableRow>
So there are multiple issues here.
1) The className is not a valid property for the Checkbox API https://material-ui.com/api/checkbox/#checkbox-api
2) console.log(event.target)
shows that the actual click happens on an svg label used to style the input and not the input itself. So, you cannot directly use inputProps={{className:"selectedCheckbox"}} either and capture the same from the classList
You can refer this sandbox and see how you can get the desired result if you actually click the input
: https://codesandbox.io/s/r7j4j638qn
So, a possible answer is to modify the icon
property of the Checkbox
component and set it to a custom icon with the specified class ? Then it should work as expected.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With