The Material UI documentation includes an example of a multiple select where the selected options are rendered with the Chip
component by using the renderValue
prop on the Select
. The standard behavior for the Select
component is that clicking on the current value opens the list of options.
I am trying to tweak this so that the Chip
s show the X
button, and clicking on the X
should instantly remove that item from the selections rather than opening the options list.
That seems easy, but I can't get the onDelete
event of the Chip
to fire. Clicking the X
still just opens the Select
.
How can I get the onDelete
event to take priority? From what I know about event bubbling, it seems like the Chip
should handle the event first.
Code Sandbox Demo
Code:
const MultipleSelectDemo = () => {
const [personName, setPersonName] = React.useState<string[]>(initialSelected);
const handleChange = (event: React.ChangeEvent<{ value: unknown }>) => {
setPersonName(event.target.value as string[]);
};
// this never gets called
const handleDelete = (e: React.MouseEvent, value: string) => {
e.preventDefault();
console.log("clicked delete");
setPersonName((current) => _without(current, value));
};
return (
<div>
<FormControl>
<InputLabel id="demo-mutiple-chip-checkbox-label">
Chip + Check
</InputLabel>
<Select
labelId="demo-mutiple-chip-checkbox-label"
id="demo-mutiple-chip-checkbox"
multiple
value={personName}
onChange={handleChange}
onOpen={() => console.log("select opened")}
IconComponent={KeyboardArrowDownIcon}
renderValue={(selected) => (
<div>
{(selected as string[]).map((value) => (
<Chip
key={value}
label={value}
clickable
className={classes.chip}
onDelete={(e) => handleDelete(e, value)}
onClick={() => console.log("clicked chip")}
/>
))}
</div>
)}
>
{names.map((name) => (
<MenuItem key={name} value={name}>
<Checkbox checked={personName.includes(name)} />
<ListItemText primary={name} />
</MenuItem>
))}
</Select>
</FormControl>
</div>
);
}
The opening of the Select
is triggered by the mouse-down event -- not the click event.
You can get your desired behavior by stopping propagation of the mouse-down event when it occurs on the delete icon of the Chip
:
<Chip
key={value}
label={value}
clickable
deleteIcon={
<CancelIcon
onMouseDown={(event) => event.stopPropagation()}
/>
}
className={classes.chip}
onDelete={(e) => handleDelete(e, value)}
onClick={() => console.log("clicked chip")}
/>
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