Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Deletable Chips in Material UI Multiple Select

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 Chips 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>
  );
}
like image 870
Linda Paiste Avatar asked Nov 03 '20 21:11

Linda Paiste


1 Answers

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")}
                  />

Edit Deletable Chip in multi-Select

like image 197
Ryan Cogswell Avatar answered Sep 30 '22 10:09

Ryan Cogswell