How to enable select all feature in material-ui/SelectField component?

12,815

Solution 1

Create a MenuItem above all the choices.

<SelectField
        multiple={true}
        hintText="Multiple Select"
        value={values}
        onChange={this.handleChange}
      >
          <MenuItem
            checked={this.state.open}
            value="Select all"
            onClick={this.selectAll}
            primaryText={checkedAll?"Select None":"Select all"}
          />
        {this.menuItems(values)}
      </SelectField>

Create a state checkedAll which is updated whenever the Select All item is clicked. Whenever the SelectAll MenuItem is clicked update the values to the required data(here unique) using a function.

selectAll = () => {
    if(this.state.checkedAll)
      this.setState(
        {values:[]}
      );
    else
      this.setState(
        {values:names}
      );
    this.setState({
      checkedAll:!this.state.checkedAll
    });
  }

Solution 2

Create a Select with multiple property and an option Select All along with other options.

Like with the single selection, you can pull out the new value by accessing event.target.value in the onChange callback. It's always an array. When Select All is clicked, the value all (in this example) will be present in the last index of the array which can be used to toggle select all or unselect all options.

*This example has a checkbox prefixed in the options.

Here's the link to the working demo in codesandbox.

const [selected, setSelected] = useState([]);

const handleChange = (event) => {
  const value = event.target.value;
  if (value[value.length - 1] === "all") {
    setSelected(selected.length === options.length ? [] : options);
    return;
  }
  setSelected(value);
};
<Select
  multiple
  value={selected}
  onChange={handleChange}
  renderValue={(selected) => selected.join(", ")}
>
  <MenuItem value="all">
    <ListItemIcon>
      <Checkbox
        checked={options.length > 0 && selected.length === options.length}
        indeterminate={selected.length > 0 && selected.length < options.length}
      />
    </ListItemIcon>
    <ListItemText primary="Select All" />
  </MenuItem>
  {options.map((option) => (
    <MenuItem key={option} value={option}>
      <ListItemIcon>
        <Checkbox checked={selected.indexOf(option) > -1} />
      </ListItemIcon>
      <ListItemText primary={option} />
    </MenuItem>
  ))}
</Select>

Solution 3

I managed to make the accepted answer work well. So please refer to the answer of anonymous_siva before reading this.

So yes, you can't make the component handle events without unpleasant side effects. But you can remove event handling from to a child with an event like this:

<MenuItem key={'Select all'}>
  <ListItemText
    primary="Select all"
    onClick={(event) => {
      event.stopPropagation();
      setValues(values);
    }}
  />
</MenuItem>

Here you can see that we need to stop propagation and update your component's state with all default options that are available.

You can do exactly the same for deselect all option, but change state to being empty.

Now, you need to manually override margins and paddings of MenuItem to zero, and make the child component take the place it needs using the padding. This will make sure that children occupies all the insides of the parent.

Solution 4

The solution of @Bhalahariharan V is good but does not take into account inputs that would have the value all. It would be thus better to add a property data-button-all to the Select all menu item.

Then, in the handle change function, check for this property to know if the select all button has been pressed or not.

const [selected, setSelected] = useState([]);
const handleChange = (event) => {
  const value = event.target.value.filter((val) => !!val);
  const isClickAll = !!(event.currentTarget as any).getAttribute('data-button-all');
  if (isClickAll) {
    setSelected(selected.length === options.length ? [] : options);
    return;
  }
  setSelected(value);
};


<Select
  multiple
  value={selected}
  onChange={handleChange}
  renderValue={(selected) => selected.join(", ")}
>
  <MenuItem data-button-all>
    <ListItemIcon>
      <Checkbox
        checked={options.length > 0 && selected.length === options.length}
        indeterminate={selected.length > 0 && selected.length < options.length}
      />
    </ListItemIcon>
    <ListItemText primary="Select All" />
  </MenuItem>
  {options.map((option) => (
    <MenuItem key={option} value={option}>
      <ListItemIcon>
        <Checkbox checked={selected.indexOf(option) > -1} />
      </ListItemIcon>
      <ListItemText primary={option} />
    </MenuItem>
  ))}
</Select>
Share:
12,815

Related videos on Youtube

user9883888
Author by

user9883888

Updated on June 04, 2022

Comments

  • user9883888
    user9883888 almost 2 years

    Document Link I am following the above document Link for implementing the Select-field component. I didnot find the proper document for select all in this component.

    Import statement for component

    import SelectField from 'material-ui/SelectField'; 
    

    Component code:

    <SelectField
        className="search_items"
        multiple={true}
        hintText="Select Item"
        value={values}
        onChange={this.handleChange} >
        {this.menuItems(values)}
     </SelectField>
    

    menuItems Function:

    menuItems(values) {
         return unique && unique.map((name) => (
            <MenuItem
                key={name}
                insetChildren={true}
                checked={values && values.indexOf(name) > -1}
                value={name}
                primaryText={name && name.concat('(').concat(sectors.filter(i => i === name).length).concat(')')}
            />
        ));
    }
    

    OnChange Function :

    handleChange(event, index, values) {
        this.setState({ values })
    }
    

    How to enable select all option for all the items to be selected. Thanks in advance

  • user9883888
    user9883888 almost 6 years
    For the first time from the values when i click on select All, All the items are not getting selected showing selected none with selected, then second time all are getting selected
  • user9883888
    user9883888 almost 6 years
    in selectAll function it should be if(!this.state.checkedall) in first line? It would work right if this is the case
  • Gergely M
    Gergely M over 4 years
    Material UI - MenuItem component doesn't support events including onClick as of today (2019-12-12) thus this solution doesn't work. I found that the ListItemText has an onClick event which can be nested into the MenuItem component - as shown at material-ui.com/components/selects/#multiple-select - "tag" menu. Although, for some reason, combining it with the Select component's onChange event caused it behaving funny and couldn't trigger any hooks from the onClick's handle.
  • Sivakumar A
    Sivakumar A over 3 years
    This solution is working perfectly in my case