How to enable select all feature in material-ui/SelectField component?
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>
Related videos on Youtube
user9883888
Updated on June 04, 2022Comments
-
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 almost 6 yearsFor 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 almost 6 yearsin selectAll function it should be if(!this.state.checkedall) in first line? It would work right if this is the case
-
Gergely M over 4 yearsMaterial UI -
MenuItem
component doesn't support events includingonClick
as of today (2019-12-12) thus this solution doesn't work. I found that theListItemText
has anonClick
event which can be nested into theMenuItem
component - as shown at material-ui.com/components/selects/#multiple-select - "tag" menu. Although, for some reason, combining it with theSelect
component'sonChange
event caused it behaving funny and couldn't trigger any hooks from the onClick's handle. -
Sivakumar A over 3 yearsThis solution is working perfectly in my case