Multiselect in Material UI is an extended feature to the regular select or dropdown menu that enables users to select multiple values within the same input field.
MUI provides a couple of convenient options to get a feature-rich multiselect component included in our project.
In this tutorial, we’ll learn how to create a multiselect component using Select and Autocomplete with a customized menu list and removable tags/chips as values.
Here is what the final code will look like:
If this is your first time working with MUI, please follow the installation instructions from the official documentation to get started.
Using Select Component
Multiselect at a basic level is similar to the regular Select component syntax except for adding multiple prop to enable multiple selections.
import React, { useState } from "react";
import {
OutlinedInput,
InputLabel,
MenuItem,
Select,
FormControl
} from "@mui/material";
const names = [
"Humaira Sims",
"Santiago Solis",
"Dawid Floyd",
"Mateo Barlow",
"Samia Navarro",
"Kaden Fields",
"Genevieve Watkins",
"Mariah Hickman",
"Rocco Richardson",
"Harris Glenn"
];
export default function MultiSelect() {
const [selectedNames, setSelectedNames] = useState([]);
return (
<FormControl sx={{ m: 1, width: 500 }}>
<InputLabel>Multiple Select</InputLabel>
<Select
multiple
value={selectedNames}
onChange={(e) => setSelectedNames(e.target.value)}
input={<OutlinedInput label="Multiple Select" />}
>
{names.map((name) => (
<MenuItem key={name} value={name}>
{name}
</MenuItem>
))}
</Select>
</FormControl>
);
}
Customize Selected Values
To customize the selected values, we need to use the renderValue prop and loop through the selected values to insert them into the component of our choice. We use Chip in this example to make it look like tags.
import React, { useState } from "react";
import {
OutlinedInput,
InputLabel,
MenuItem,
Select,
FormControl,
Stack,
Chip
} from "@mui/material";
const names = [
"Humaira Sims",
"Santiago Solis",
"Dawid Floyd",
"Mateo Barlow",
"Samia Navarro",
"Kaden Fields",
"Genevieve Watkins",
"Mariah Hickman",
"Rocco Richardson",
"Harris Glenn"
];
export default function MultiSelect() {
const [selectedNames, setSelectedNames] = useState([]);
return (
<FormControl sx={{ m: 1, width: 500 }}>
<InputLabel>Multiple Select</InputLabel>
<Select
multiple
value={selectedNames}
onChange={(e) => setSelectedNames(e.target.value)}
input={<OutlinedInput label="Multiple Select" />}
renderValue={(selected) => (
<Stack gap={1} direction="row" flexWrap="wrap">
{selected.map((value) => (
<Chip key={value} label={value} />
))}
</Stack>
)}
>
{names.map((name) => (
<MenuItem key={name} value={name}>
{name}
</MenuItem>
))}
</Select>
</FormControl>
);
}
We also added a Stack wrapper to align tags horizontally.
Remove Selected Values
To delete selected values, we need to define an onDelete handler and add a deleteIcon to display on the Chip component.
import React, { useState } from "react";
import {
OutlinedInput,
InputLabel,
MenuItem,
Select,
FormControl,
Stack,
Chip
} from "@mui/material";
import CancelIcon from "@mui/icons-material/Cancel";
const names = [
"Humaira Sims",
"Santiago Solis",
"Dawid Floyd",
"Mateo Barlow",
"Samia Navarro",
"Kaden Fields",
"Genevieve Watkins",
"Mariah Hickman",
"Rocco Richardson",
"Harris Glenn"
];
export default function MultiSelect() {
const [selectedNames, setSelectedNames] = useState([]);
return (
<FormControl sx={{ m: 1, width: 500 }}>
<InputLabel>Multiple Select</InputLabel>
<Select
multiple
value={selectedNames}
onChange={(e) => setSelectedNames(e.target.value)}
input={<OutlinedInput label="Multiple Select" />}
renderValue={(selected) => (
<Stack gap={1} direction="row" flexWrap="wrap">
{selected.map((value) => (
<Chip
key={value}
label={value}
onDelete={() =>
setSelectedNames(
selectedNames.filter((item) => item !== value)
)
}
deleteIcon={
<CancelIcon
onMouseDown={(event) => event.stopPropagation()}
/>
}
/>
))}
</Stack>
)}
>
{names.map((name) => (
<MenuItem key={name} value={name}>
{name}
</MenuItem>
))}
</Select>
</FormControl>
);
}
Notice that we added an onMouseDown handler to stop the Select from opening the list as the user clicks the “Cancel” icon. It’s a small required hack because of some limitations on the Select component.
Customize Menu Item
MenuItem is the component used to display all available options, and currently, any selected value has a light background color. Below, we will enhance it by adding a checkmark icon to make selections more visible.
import React, { useState } from "react";
import {
OutlinedInput,
InputLabel,
MenuItem,
Select,
FormControl,
Stack,
Chip
} from "@mui/material";
import CancelIcon from "@mui/icons-material/Cancel";
import CheckIcon from "@mui/icons-material/Check";
const names = [
"Humaira Sims",
"Santiago Solis",
"Dawid Floyd",
"Mateo Barlow",
"Samia Navarro",
"Kaden Fields",
"Genevieve Watkins",
"Mariah Hickman",
"Rocco Richardson",
"Harris Glenn"
];
export default function MultiSelect() {
const [selectedNames, setSelectedNames] = useState([]);
return (
<FormControl sx={{ m: 1, width: 500 }}>
<InputLabel>Multiple Select</InputLabel>
<Select
multiple
value={selectedNames}
onChange={(e) => setSelectedNames(e.target.value)}
input={<OutlinedInput label="Multiple Select" />}
renderValue={(selected) => (
<Stack gap={1} direction="row" flexWrap="wrap">
{selected.map((value) => (
<Chip
key={value}
label={value}
onDelete={() =>
setSelectedNames(
selectedNames.filter((item) => item !== value)
)
}
deleteIcon={
<CancelIcon
onMouseDown={(event) => event.stopPropagation()}
/>
}
/>
))}
</Stack>
)}
>
{names.map((name) => (
<MenuItem
key={name}
value={name}
sx={{ justifyContent: "space-between" }}
>
{name}
{selectedNames.includes(name) ? <CheckIcon color="info" /> : null}
</MenuItem>
))}
</Select>
</FormControl>
);
}
Using Autocomplete Component
Autocomplete is similar to the Select component in terms of providing a list of options with a multiselect feature. However, it’s a regular text input enhanced by a panel of suggested options and can be an excellent alternative for more advanced features.
For example, the basic usage below will provide us with all the features we customized in the previous section and more!
import React from "react";
import { TextField, Autocomplete } from "@mui/material";
const names = [
"Humaira Sims",
"Santiago Solis",
"Dawid Floyd",
"Mateo Barlow",
"Samia Navarro",
"Kaden Fields",
"Genevieve Watkins",
"Mariah Hickman",
"Rocco Richardson",
"Harris Glenn"
];
export default function MultiSelect() {
return (
<Autocomplete
sx={{ m: 1, width: 500 }}
multiple
options={names}
getOptionLabel={(option) => option}
disableCloseOnSelect
renderInput={(params) => (
<TextField
{...params}
variant="outlined"
label="Multiple Autocomplete"
placeholder="Multiple Autocomplete"
/>
)}
/>
);
}
As we can see above, the code is shorter than the Select component, and we get the following functionalities out of the box:
- Autocomplete on user input.
Chipcomponent for selected values by default.- Multiselect with adding and removing all values option.
Additionally, we are no longer required to add useState to the manage list. Instead, we can use the onChange prop to detect any value changes in the list.
For reference, this link has the official Autocomplete component API from Material UI
The only thing we are missing is adding a check mark on selected values. We can use similar code from the previous section using the MenuItem component, but we no longer need to loop through the list. Instead, Autocomplete provides a renderOption prop fired on every item.
import React from "react";
import { TextField, Autocomplete, MenuItem } from "@mui/material";
import CheckIcon from "@mui/icons-material/Check";
const names = [
"Humaira Sims",
"Santiago Solis",
"Dawid Floyd",
"Mateo Barlow",
"Samia Navarro",
"Kaden Fields",
"Genevieve Watkins",
"Mariah Hickman",
"Rocco Richardson",
"Harris Glenn"
];
export default function MultiSelect() {
return (
<Autocomplete
sx={{ m: 1, width: 500 }}
multiple
options={names}
getOptionLabel={(option) => option}
disableCloseOnSelect
renderInput={(params) => (
<TextField
{...params}
variant="outlined"
label="Multiple Autocomplete"
placeholder="Multiple Autocomplete"
/>
)}
renderOption={(props, option, { selected }) => (
<MenuItem
{...props}
key={option}
value={option}
sx={{ justifyContent: "space-between" }}
>
{option}
{selected ? <CheckIcon color="info" /> : null}
</MenuItem>
)}
/>
);
}
Summary
Both components are great for implementing a multiselect feature. However, the Select component is sufficient if we are looking for a simple solution without adding, removing, and auto-completing. Otherwise, Autocomplete is recommended for more advanced features.
Bye for now 👋
If you enjoyed this post, I regularly share similar content on Twitter. Follow me @muhimasri to stay up to date, or feel free to message me on Twitter if you have any questions or comments. I'm always open to discussing the topics I write about!




