@mui/material
Version:
Material UI is an open-source React component library that implements Google's Material Design. It's comprehensive and can be used in production out of the box.
1,399 lines (1,213 loc) • 43.5 kB
Markdown
---
productId: material-ui
title: React Select component
components: Select, NativeSelect
githubLabel: 'scope: select'
materialDesign: https://m2.material.io/components/menus#exposed-dropdown-menu
waiAria: https://www.w3.org/WAI/ARIA/apg/patterns/combobox/examples/combobox-select-only/
githubSource: packages/mui-material/src/Select
---
# Select
Select components are used for collecting user provided information from a list of options.
## Basic select
Menus are positioned under their emitting elements, unless they are close to the bottom of the viewport.
```tsx
import * as React from 'react';
import Box from '@mui/material/Box';
import InputLabel from '@mui/material/InputLabel';
import MenuItem from '@mui/material/MenuItem';
import FormControl from '@mui/material/FormControl';
import Select, { SelectChangeEvent } from '@mui/material/Select';
export default function BasicSelect() {
const [age, setAge] = React.useState('');
const handleChange = (event: SelectChangeEvent) => {
setAge(event.target.value as string);
};
return (
<Box sx={{ minWidth: 120 }}>
<FormControl fullWidth>
<InputLabel id="demo-simple-select-label">Age</InputLabel>
<Select
labelId="demo-simple-select-label"
id="demo-simple-select"
value={age}
label="Age"
onChange={handleChange}
>
<MenuItem value={10}>Ten</MenuItem>
<MenuItem value={20}>Twenty</MenuItem>
<MenuItem value={30}>Thirty</MenuItem>
</Select>
</FormControl>
</Box>
);
}
```
## Advanced features
The Select component is meant to be interchangeable with a native `<select>` element.
If you are looking for more advanced features, like combobox, multiselect, autocomplete, async or creatable support, head to the [`Autocomplete` component](/material-ui/react-autocomplete/).
It's meant to be an improved version of the "react-select" and "downshift" packages.
## Props
The Select component is implemented as a custom `<input>` element of the [InputBase](/material-ui/api/input-base/).
It extends the [text field components](/material-ui/react-text-field/) subcomponents, either the [OutlinedInput](/material-ui/api/outlined-input/), [Input](/material-ui/api/input/), or [FilledInput](/material-ui/api/filled-input/), depending on the variant selected.
It shares the same styles and many of the same props. Refer to the respective component's API page for details.
:::warning
Unlike input components, the `placeholder` prop is not available in Select. To add a placeholder, refer to the [placeholder](#placeholder) section below.
:::
### Variants
```tsx
import * as React from 'react';
import InputLabel from '@mui/material/InputLabel';
import MenuItem from '@mui/material/MenuItem';
import FormControl from '@mui/material/FormControl';
import Select, { SelectChangeEvent } from '@mui/material/Select';
export default function SelectVariants() {
const [age, setAge] = React.useState('');
const handleChange = (event: SelectChangeEvent) => {
setAge(event.target.value);
};
return (
<div>
<FormControl variant="outlined" sx={{ m: 1, minWidth: 120 }}>
<InputLabel id="demo-simple-select-outlined-label">Age</InputLabel>
<Select
labelId="demo-simple-select-outlined-label"
id="demo-simple-select-outlined"
value={age}
onChange={handleChange}
label="Age"
>
<MenuItem value="">
<em>None</em>
</MenuItem>
<MenuItem value={10}>Ten</MenuItem>
<MenuItem value={20}>Twenty</MenuItem>
<MenuItem value={30}>Thirty</MenuItem>
</Select>
</FormControl>
<FormControl variant="standard" sx={{ m: 1, minWidth: 120 }}>
<InputLabel id="demo-simple-select-standard-label">Age</InputLabel>
<Select
labelId="demo-simple-select-standard-label"
id="demo-simple-select-standard"
value={age}
onChange={handleChange}
>
<MenuItem value="">
<em>None</em>
</MenuItem>
<MenuItem value={10}>Ten</MenuItem>
<MenuItem value={20}>Twenty</MenuItem>
<MenuItem value={30}>Thirty</MenuItem>
</Select>
</FormControl>
<FormControl variant="filled" sx={{ m: 1, minWidth: 120 }}>
<InputLabel id="demo-simple-select-filled-label">Age</InputLabel>
<Select
labelId="demo-simple-select-filled-label"
id="demo-simple-select-filled"
value={age}
onChange={handleChange}
>
<MenuItem value="">
<em>None</em>
</MenuItem>
<MenuItem value={10}>Ten</MenuItem>
<MenuItem value={20}>Twenty</MenuItem>
<MenuItem value={30}>Thirty</MenuItem>
</Select>
</FormControl>
</div>
);
}
```
:::warning
Note that when using FormControl with the outlined variant of the Select, you need to provide a label in two places: in the InputLabel component and in the `label` prop of the Select component (see the above demo). This is needed for the label floating animation to work correctly.
:::
### Labels and helper text
Select always needs an accessible name. This can come from an associated visible label, such as an `InputLabel` linked to the `Select` with `labelId` or from adding an `aria-label` prop to the input element props (`inputProps`). If more information is needed, provide a helper text element and link it to the `Select` using `aria-describedby`.
```tsx
import * as React from 'react';
import InputLabel from '@mui/material/InputLabel';
import MenuItem from '@mui/material/MenuItem';
import FormHelperText from '@mui/material/FormHelperText';
import FormControl from '@mui/material/FormControl';
import Select, { SelectChangeEvent } from '@mui/material/Select';
export default function SelectLabels() {
const id = React.useId();
const noLabelId = React.useId();
const [age, setAge] = React.useState('');
const handleChange = (event: SelectChangeEvent) => {
setAge(event.target.value);
};
return (
<div>
<FormControl sx={{ m: 1, minWidth: 120 }}>
<InputLabel id={`${id}-label`}>Age</InputLabel>
<Select
aria-describedby={`${id}-helper-text`}
labelId={`${id}-label`}
id={id}
value={age}
label="Age"
onChange={handleChange}
>
<MenuItem value="">
<em>None</em>
</MenuItem>
<MenuItem value={10}>Ten</MenuItem>
<MenuItem value={20}>Twenty</MenuItem>
<MenuItem value={30}>Thirty</MenuItem>
</Select>
<FormHelperText id={`${id}-helper-text`}>
Visible label and helper text
</FormHelperText>
</FormControl>
<FormControl sx={{ m: 1, minWidth: 120 }}>
<Select
aria-describedby={`${noLabelId}-helper-text`}
value={age}
onChange={handleChange}
displayEmpty
inputProps={{ 'aria-label': 'Age' }}
>
<MenuItem value="">
<em>None</em>
</MenuItem>
<MenuItem value={10}>Ten</MenuItem>
<MenuItem value={20}>Twenty</MenuItem>
<MenuItem value={30}>Thirty</MenuItem>
</Select>
<FormHelperText id={`${noLabelId}-helper-text`}>
aria-label and helper text
</FormHelperText>
</FormControl>
</div>
);
}
```
### Auto width
```tsx
import * as React from 'react';
import InputLabel from '@mui/material/InputLabel';
import MenuItem from '@mui/material/MenuItem';
import FormControl from '@mui/material/FormControl';
import Select, { SelectChangeEvent } from '@mui/material/Select';
export default function SelectAutoWidth() {
const [age, setAge] = React.useState('');
const handleChange = (event: SelectChangeEvent) => {
setAge(event.target.value);
};
return (
<div>
<FormControl sx={{ m: 1, minWidth: 80 }}>
<InputLabel id="demo-simple-select-autowidth-label">Age</InputLabel>
<Select
labelId="demo-simple-select-autowidth-label"
id="demo-simple-select-autowidth"
value={age}
onChange={handleChange}
autoWidth
label="Age"
>
<MenuItem value="">
<em>None</em>
</MenuItem>
<MenuItem value={20}>Twenty</MenuItem>
<MenuItem value={21}>Twenty one</MenuItem>
<MenuItem value={22}>Twenty one and a half</MenuItem>
</Select>
</FormControl>
</div>
);
}
```
### Small Size
```tsx
import * as React from 'react';
import InputLabel from '@mui/material/InputLabel';
import MenuItem from '@mui/material/MenuItem';
import FormControl from '@mui/material/FormControl';
import Select, { SelectChangeEvent } from '@mui/material/Select';
export default function SelectSmall() {
const [age, setAge] = React.useState('');
const handleChange = (event: SelectChangeEvent) => {
setAge(event.target.value);
};
return (
<FormControl sx={{ m: 1, minWidth: 120 }} size="small">
<InputLabel id="demo-select-small-label">Age</InputLabel>
<Select
labelId="demo-select-small-label"
id="demo-select-small"
value={age}
label="Age"
onChange={handleChange}
>
<MenuItem value="">
<em>None</em>
</MenuItem>
<MenuItem value={10}>Ten</MenuItem>
<MenuItem value={20}>Twenty</MenuItem>
<MenuItem value={30}>Thirty</MenuItem>
</Select>
</FormControl>
);
}
```
### Other props
```tsx
import * as React from 'react';
import InputLabel from '@mui/material/InputLabel';
import MenuItem from '@mui/material/MenuItem';
import FormHelperText from '@mui/material/FormHelperText';
import FormControl from '@mui/material/FormControl';
import Select, { SelectChangeEvent } from '@mui/material/Select';
export default function SelectOtherProps() {
const [age, setAge] = React.useState('');
const handleChange = (event: SelectChangeEvent) => {
setAge(event.target.value);
};
return (
<div>
<FormControl sx={{ m: 1, minWidth: 120 }} disabled>
<InputLabel id="demo-simple-select-disabled-label">Age</InputLabel>
<Select
labelId="demo-simple-select-disabled-label"
id="demo-simple-select-disabled"
value={age}
label="Age"
onChange={handleChange}
>
<MenuItem value="">
<em>None</em>
</MenuItem>
<MenuItem value={10}>Ten</MenuItem>
<MenuItem value={20}>Twenty</MenuItem>
<MenuItem value={30}>Thirty</MenuItem>
</Select>
<FormHelperText>Disabled</FormHelperText>
</FormControl>
<FormControl sx={{ m: 1, minWidth: 120 }} error>
<InputLabel id="demo-simple-select-error-label">Age</InputLabel>
<Select
labelId="demo-simple-select-error-label"
id="demo-simple-select-error"
value={age}
label="Age"
onChange={handleChange}
renderValue={(value) => `⚠️ - ${value}`}
>
<MenuItem value="">
<em>None</em>
</MenuItem>
<MenuItem value={10}>Ten</MenuItem>
<MenuItem value={20}>Twenty</MenuItem>
<MenuItem value={30}>Thirty</MenuItem>
</Select>
<FormHelperText>Error</FormHelperText>
</FormControl>
<FormControl sx={{ m: 1, minWidth: 120 }}>
<InputLabel id="demo-simple-select-readonly-label">Age</InputLabel>
<Select
labelId="demo-simple-select-readonly-label"
id="demo-simple-select-readonly"
value={age}
label="Age"
onChange={handleChange}
inputProps={{ readOnly: true }}
>
<MenuItem value="">
<em>None</em>
</MenuItem>
<MenuItem value={10}>Ten</MenuItem>
<MenuItem value={20}>Twenty</MenuItem>
<MenuItem value={30}>Thirty</MenuItem>
</Select>
<FormHelperText>Read only</FormHelperText>
</FormControl>
<FormControl required sx={{ m: 1, minWidth: 120 }}>
<InputLabel id="demo-simple-select-required-label">Age</InputLabel>
<Select
labelId="demo-simple-select-required-label"
id="demo-simple-select-required"
value={age}
label="Age *"
onChange={handleChange}
>
<MenuItem value="">
<em>None</em>
</MenuItem>
<MenuItem value={10}>Ten</MenuItem>
<MenuItem value={20}>Twenty</MenuItem>
<MenuItem value={30}>Thirty</MenuItem>
</Select>
<FormHelperText>Required</FormHelperText>
</FormControl>
</div>
);
}
```
## Native select
As the user experience can be improved on mobile using the native select of the platform,
we allow such pattern.
```tsx
import * as React from 'react';
import Box from '@mui/material/Box';
import InputLabel from '@mui/material/InputLabel';
import FormControl from '@mui/material/FormControl';
import NativeSelect from '@mui/material/NativeSelect';
export default function NativeSelectDemo() {
const id = React.useId();
return (
<Box sx={{ minWidth: 120 }}>
<FormControl fullWidth>
<InputLabel variant="standard" htmlFor={`${id}-select`}>
Age
</InputLabel>
<NativeSelect
defaultValue={30}
inputProps={{
name: 'age',
id: `${id}-select`,
}}
>
<option value={10}>Ten</option>
<option value={20}>Twenty</option>
<option value={30}>Thirty</option>
</NativeSelect>
</FormControl>
</Box>
);
}
```
## TextField
The `TextField` wrapper component is a complete form control including a label, input and help text.
You can find an example with the select mode [in this section](/material-ui/react-text-field/#select).
## Customization
Here are some examples of customizing the component.
You can learn more about this in the [overrides documentation page](/material-ui/customization/how-to-customize/).
The first step is to style the `InputBase` component.
Once it's styled, you can either use it directly as a text field or provide it to the select `input` prop to have a `select` field.
Notice that the `"standard"` variant is easier to customize, since it does not wrap the contents in a `fieldset`/`legend` markup.
```tsx
import * as React from 'react';
import { styled } from '@mui/material/styles';
import InputLabel from '@mui/material/InputLabel';
import MenuItem from '@mui/material/MenuItem';
import FormControl from '@mui/material/FormControl';
import Select from '@mui/material/Select';
import NativeSelect from '@mui/material/NativeSelect';
import InputBase from '@mui/material/InputBase';
const BootstrapInput = styled(InputBase)(({ theme }) => ({
'label + &': {
marginTop: theme.spacing(3),
},
'& .MuiInputBase-input': {
borderRadius: 4,
position: 'relative',
backgroundColor: (theme.vars ?? theme).palette.background.paper,
border: '1px solid #ced4da',
fontSize: 16,
padding: '10px 26px 10px 12px',
transition: theme.transitions.create(['border-color', 'box-shadow']),
// Use the system font instead of the default Roboto font.
fontFamily: [
'-apple-system',
'BlinkMacSystemFont',
'"Segoe UI"',
'Roboto',
'"Helvetica Neue"',
'Arial',
'sans-serif',
'"Apple Color Emoji"',
'"Segoe UI Emoji"',
'"Segoe UI Symbol"',
].join(','),
'&:focus': {
borderRadius: 4,
borderColor: '#80bdff',
boxShadow: '0 0 0 0.2rem rgba(0,123,255,.25)',
},
},
}));
export default function CustomizedSelects() {
const textboxId = React.useId();
const selectId = React.useId();
const nativeId = React.useId();
const [age, setAge] = React.useState('');
const handleChange = (event: { target: { value: string } }) => {
setAge(event.target.value);
};
return (
<div>
<FormControl sx={{ m: 1 }} variant="standard">
<InputLabel htmlFor={`${textboxId}-input`}>Age</InputLabel>
<BootstrapInput id={`${textboxId}-input`} />
</FormControl>
<FormControl sx={{ m: 1 }} variant="standard">
<InputLabel id={`${selectId}-label`}>Age</InputLabel>
<Select
labelId={`${selectId}-label`}
id={`${selectId}-select`}
value={age}
onChange={handleChange}
input={<BootstrapInput />}
>
<MenuItem value="">
<em>None</em>
</MenuItem>
<MenuItem value={10}>Ten</MenuItem>
<MenuItem value={20}>Twenty</MenuItem>
<MenuItem value={30}>Thirty</MenuItem>
</Select>
</FormControl>
<FormControl sx={{ m: 1 }} variant="standard">
<InputLabel htmlFor={`${nativeId}-select`}>Age</InputLabel>
<NativeSelect
id={`${nativeId}-select`}
value={age}
onChange={handleChange}
input={<BootstrapInput />}
>
<option aria-label="None" value="" />
<option value={10}>Ten</option>
<option value={20}>Twenty</option>
<option value={30}>Thirty</option>
</NativeSelect>
</FormControl>
</div>
);
}
```
🎨 If you are looking for inspiration, you can check [MUI Treasury's customization examples](https://mui-treasury.com/primitive/select).
## Multiple select
The `Select` component can handle multiple selections.
It's enabled with the `multiple` prop.
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.
### Default
```tsx
import * as React from 'react';
import { Theme, useTheme } from '@mui/material/styles';
import OutlinedInput from '@mui/material/OutlinedInput';
import InputLabel from '@mui/material/InputLabel';
import MenuItem from '@mui/material/MenuItem';
import FormControl from '@mui/material/FormControl';
import Select, { SelectChangeEvent } from '@mui/material/Select';
const ITEM_HEIGHT = 48;
const ITEM_PADDING_TOP = 8;
const MenuProps = {
slotProps: {
paper: {
style: {
maxHeight: ITEM_HEIGHT * 4.5 + ITEM_PADDING_TOP,
width: 250,
},
},
},
};
const names = [
'Oliver Hansen',
'Van Henry',
'April Tucker',
'Ralph Hubbard',
'Omar Alexander',
'Carlos Abbott',
'Miriam Wagner',
'Bradley Wilkerson',
'Virginia Andrews',
'Kelly Snyder',
];
function getStyles(name: string, personName: string[], theme: Theme) {
return {
fontWeight: personName.includes(name)
? theme.typography.fontWeightMedium
: theme.typography.fontWeightRegular,
};
}
export default function MultipleSelect() {
const theme = useTheme();
const [personName, setPersonName] = React.useState<string[]>([]);
const handleChange = (event: SelectChangeEvent<typeof personName>) => {
const {
target: { value },
} = event;
setPersonName(
// On autofill we get a stringified value.
typeof value === 'string' ? value.split(',') : value,
);
};
return (
<div>
<FormControl sx={{ m: 1, width: 300 }}>
<InputLabel id="demo-multiple-name-label">Name</InputLabel>
<Select
labelId="demo-multiple-name-label"
id="demo-multiple-name"
multiple
value={personName}
onChange={handleChange}
input={<OutlinedInput label="Name" />}
MenuProps={MenuProps}
>
{names.map((name) => (
<MenuItem
key={name}
value={name}
style={getStyles(name, personName, theme)}
>
{name}
</MenuItem>
))}
</Select>
</FormControl>
</div>
);
}
```
### Selection indicators
This example demonstrates how icons are used to indicate the selection state of each item in the listbox.
```tsx
import * as React from 'react';
import OutlinedInput from '@mui/material/OutlinedInput';
import InputLabel from '@mui/material/InputLabel';
import MenuItem from '@mui/material/MenuItem';
import FormControl from '@mui/material/FormControl';
import ListItemText from '@mui/material/ListItemText';
import Select, { SelectChangeEvent } from '@mui/material/Select';
import CheckBoxOutlineBlankIcon from '@mui/icons-material/CheckBoxOutlineBlank';
import CheckBoxIcon from '@mui/icons-material/CheckBox';
const ITEM_HEIGHT = 48;
const ITEM_PADDING_TOP = 8;
const MenuProps = {
slotProps: {
paper: {
style: {
maxHeight: ITEM_HEIGHT * 4.5 + ITEM_PADDING_TOP,
width: 250,
},
},
},
};
const names = [
'Oliver Hansen',
'Van Henry',
'April Tucker',
'Ralph Hubbard',
'Omar Alexander',
'Carlos Abbott',
'Miriam Wagner',
'Bradley Wilkerson',
'Virginia Andrews',
'Kelly Snyder',
];
export default function MultipleSelectCheckmarks() {
const [personName, setPersonName] = React.useState<string[]>([]);
const handleChange = (event: SelectChangeEvent<typeof personName>) => {
const {
target: { value },
} = event;
setPersonName(
// On autofill we get a stringified value.
typeof value === 'string' ? value.split(',') : value,
);
};
return (
<div>
<FormControl sx={{ m: 1, width: 300 }}>
<InputLabel id="demo-multiple-checkbox-label">Tag</InputLabel>
<Select
labelId="demo-multiple-checkbox-label"
id="demo-multiple-checkbox"
multiple
value={personName}
onChange={handleChange}
input={<OutlinedInput label="Tag" />}
renderValue={(selected) => selected.join(', ')}
MenuProps={MenuProps}
>
{names.map((name) => {
const selected = personName.includes(name);
const SelectionIcon = selected ? CheckBoxIcon : CheckBoxOutlineBlankIcon;
return (
<MenuItem key={name} value={name}>
<SelectionIcon
fontSize="small"
style={{ marginRight: 8, padding: 9, boxSizing: 'content-box' }}
/>
<ListItemText primary={name} />
</MenuItem>
);
})}
</Select>
</FormControl>
</div>
);
}
```
### Chip
```tsx
import * as React from 'react';
import { Theme, useTheme } from '@mui/material/styles';
import Box from '@mui/material/Box';
import OutlinedInput from '@mui/material/OutlinedInput';
import InputLabel from '@mui/material/InputLabel';
import MenuItem from '@mui/material/MenuItem';
import FormControl from '@mui/material/FormControl';
import Select, { SelectChangeEvent } from '@mui/material/Select';
import Chip from '@mui/material/Chip';
const ITEM_HEIGHT = 48;
const ITEM_PADDING_TOP = 8;
const MenuProps = {
slotProps: {
paper: {
style: {
maxHeight: ITEM_HEIGHT * 4.5 + ITEM_PADDING_TOP,
width: 250,
},
},
},
};
const names = [
'Oliver Hansen',
'Van Henry',
'April Tucker',
'Ralph Hubbard',
'Omar Alexander',
'Carlos Abbott',
'Miriam Wagner',
'Bradley Wilkerson',
'Virginia Andrews',
'Kelly Snyder',
];
function getStyles(name: string, personName: readonly string[], theme: Theme) {
return {
fontWeight: personName.includes(name)
? theme.typography.fontWeightMedium
: theme.typography.fontWeightRegular,
};
}
export default function MultipleSelectChip() {
const theme = useTheme();
const [personName, setPersonName] = React.useState<string[]>([]);
const handleChange = (event: SelectChangeEvent<typeof personName>) => {
const {
target: { value },
} = event;
setPersonName(
// On autofill we get a stringified value.
typeof value === 'string' ? value.split(',') : value,
);
};
return (
<div>
<FormControl sx={{ m: 1, width: 300 }}>
<InputLabel id="demo-multiple-chip-label">Chip</InputLabel>
<Select
labelId="demo-multiple-chip-label"
id="demo-multiple-chip"
multiple
value={personName}
onChange={handleChange}
input={<OutlinedInput id="select-multiple-chip" label="Chip" />}
renderValue={(selected) => (
<Box sx={{ display: 'flex', flexWrap: 'wrap', gap: 0.5 }}>
{selected.map((value) => (
<Chip key={value} label={value} />
))}
</Box>
)}
MenuProps={MenuProps}
>
{names.map((name) => (
<MenuItem
key={name}
value={name}
style={getStyles(name, personName, theme)}
>
{name}
</MenuItem>
))}
</Select>
</FormControl>
</div>
);
}
```
### Placeholder
```tsx
import * as React from 'react';
import { Theme, useTheme } from '@mui/material/styles';
import OutlinedInput from '@mui/material/OutlinedInput';
import MenuItem from '@mui/material/MenuItem';
import FormControl from '@mui/material/FormControl';
import Select, { SelectChangeEvent } from '@mui/material/Select';
const ITEM_HEIGHT = 48;
const ITEM_PADDING_TOP = 8;
const MenuProps = {
slotProps: {
paper: {
style: {
maxHeight: ITEM_HEIGHT * 4.5 + ITEM_PADDING_TOP,
width: 250,
},
},
},
};
const names = [
'Oliver Hansen',
'Van Henry',
'April Tucker',
'Ralph Hubbard',
'Omar Alexander',
'Carlos Abbott',
'Miriam Wagner',
'Bradley Wilkerson',
'Virginia Andrews',
'Kelly Snyder',
];
function getStyles(name: string, personName: readonly string[], theme: Theme) {
return {
fontWeight: personName.includes(name)
? theme.typography.fontWeightMedium
: theme.typography.fontWeightRegular,
};
}
export default function MultipleSelectPlaceholder() {
const theme = useTheme();
const [personName, setPersonName] = React.useState<string[]>([]);
const handleChange = (event: SelectChangeEvent<typeof personName>) => {
const {
target: { value },
} = event;
setPersonName(
// On autofill we get a stringified value.
typeof value === 'string' ? value.split(',') : value,
);
};
return (
<div>
<FormControl sx={{ m: 1, width: 300, mt: 3 }}>
<Select
multiple
displayEmpty
value={personName}
onChange={handleChange}
input={<OutlinedInput />}
renderValue={(selected) => {
if (selected.length === 0) {
return <em>Placeholder</em>;
}
return selected.join(', ');
}}
MenuProps={MenuProps}
inputProps={{ 'aria-label': 'Without label' }}
>
<MenuItem disabled value="">
<em>Placeholder</em>
</MenuItem>
{names.map((name) => (
<MenuItem
key={name}
value={name}
style={getStyles(name, personName, theme)}
>
{name}
</MenuItem>
))}
</Select>
</FormControl>
</div>
);
}
```
### Native
```tsx
import * as React from 'react';
import InputLabel from '@mui/material/InputLabel';
import FormControl from '@mui/material/FormControl';
import Select from '@mui/material/Select';
const names = [
'Oliver Hansen',
'Van Henry',
'April Tucker',
'Ralph Hubbard',
'Omar Alexander',
'Carlos Abbott',
'Miriam Wagner',
'Bradley Wilkerson',
'Virginia Andrews',
'Kelly Snyder',
];
export default function MultipleSelectNative() {
const id = React.useId();
const [personName, setPersonName] = React.useState<string[]>([]);
const handleChangeMultiple = (event: React.ChangeEvent<HTMLSelectElement>) => {
const { options } = event.target;
const value: string[] = [];
for (let i = 0, l = options.length; i < l; i += 1) {
if (options[i].selected) {
value.push(options[i].value);
}
}
setPersonName(value);
};
return (
<div>
<FormControl sx={{ m: 1, minWidth: 120, maxWidth: 300 }}>
<InputLabel shrink htmlFor={`${id}-select`}>
Native
</InputLabel>
<Select<string[]>
multiple
native
value={personName}
// @ts-ignore Typings are not considering `native`
onChange={handleChangeMultiple}
label="Native"
inputProps={{
id: `${id}-select`,
}}
>
{names.map((name) => (
<option key={name} value={name}>
{name}
</option>
))}
</Select>
</FormControl>
</div>
);
}
```
## Controlling the open state
You can control the open state of the select with the `open` prop. Alternatively, it is also possible to set the initial (uncontrolled) open state of the component with the `defaultOpen` prop.
:::info
- A component is **controlled** when it's managed by its parent using props.
- A component is **uncontrolled** when it's managed by its own local state.
Learn more about controlled and uncontrolled components in the [React documentation](https://react.dev/learn/sharing-state-between-components#controlled-and-uncontrolled-components).
:::
```tsx
import * as React from 'react';
import InputLabel from '@mui/material/InputLabel';
import MenuItem from '@mui/material/MenuItem';
import FormControl from '@mui/material/FormControl';
import Select, { SelectChangeEvent } from '@mui/material/Select';
import Button from '@mui/material/Button';
export default function ControlledOpenSelect() {
const [age, setAge] = React.useState<string | number>('');
const [open, setOpen] = React.useState(false);
const handleChange = (event: SelectChangeEvent<typeof age>) => {
setAge(event.target.value);
};
const handleClose = () => {
setOpen(false);
};
const handleOpen = () => {
setOpen(true);
};
return (
<div>
<Button sx={{ display: 'block', mt: 2 }} onClick={handleOpen}>
Open the select
</Button>
<FormControl sx={{ m: 1, minWidth: 120 }}>
<InputLabel id="demo-controlled-open-select-label">Age</InputLabel>
<Select
labelId="demo-controlled-open-select-label"
id="demo-controlled-open-select"
open={open}
onClose={handleClose}
onOpen={handleOpen}
value={age}
label="Age"
onChange={handleChange}
>
<MenuItem value="">
<em>None</em>
</MenuItem>
<MenuItem value={10}>Ten</MenuItem>
<MenuItem value={20}>Twenty</MenuItem>
<MenuItem value={30}>Thirty</MenuItem>
</Select>
</FormControl>
</div>
);
}
```
## With a dialog
While it's discouraged by the Material Design guidelines, you can use a select inside a dialog.
```tsx
import * as React from 'react';
import Box from '@mui/material/Box';
import Button from '@mui/material/Button';
import Dialog from '@mui/material/Dialog';
import DialogActions from '@mui/material/DialogActions';
import DialogContent from '@mui/material/DialogContent';
import DialogTitle from '@mui/material/DialogTitle';
import InputLabel from '@mui/material/InputLabel';
import OutlinedInput from '@mui/material/OutlinedInput';
import MenuItem from '@mui/material/MenuItem';
import FormControl from '@mui/material/FormControl';
import Select, { SelectChangeEvent } from '@mui/material/Select';
export default function DialogSelect() {
const nativeId = React.useId();
const selectId = React.useId();
const [open, setOpen] = React.useState(false);
const [age, setAge] = React.useState<number | string>('');
const handleChange = (event: SelectChangeEvent<typeof age>) => {
setAge(Number(event.target.value) || '');
};
const handleClickOpen = () => {
setOpen(true);
};
const handleDialogClose = (
_event: React.SyntheticEvent<unknown>,
reason: string,
) => {
if (!['backdropClick', 'escapeKeyDown'].includes(reason)) {
setOpen(false);
}
};
const handleActionButtonClick = () => {
setOpen(false);
};
return (
<div>
<Button onClick={handleClickOpen}>Open select dialog</Button>
<Dialog open={open} onClose={handleDialogClose}>
<DialogTitle>Fill the form</DialogTitle>
<DialogContent>
<Box component="form" sx={{ display: 'flex', flexWrap: 'wrap' }}>
<FormControl sx={{ m: 1, minWidth: 120 }}>
<InputLabel htmlFor={`${nativeId}-select`}>Age</InputLabel>
<Select
native
value={age}
onChange={handleChange}
input={<OutlinedInput label="Age" id={`${nativeId}-select`} />}
>
<option aria-label="None" value="" />
<option value={10}>Ten</option>
<option value={20}>Twenty</option>
<option value={30}>Thirty</option>
</Select>
</FormControl>
<FormControl sx={{ m: 1, minWidth: 120 }}>
<InputLabel id={`${selectId}-label`}>Age</InputLabel>
<Select
labelId={`${selectId}-label`}
id={`${selectId}-select`}
value={age}
onChange={handleChange}
input={<OutlinedInput label="Age" />}
>
<MenuItem value="">
<em>None</em>
</MenuItem>
<MenuItem value={10}>Ten</MenuItem>
<MenuItem value={20}>Twenty</MenuItem>
<MenuItem value={30}>Thirty</MenuItem>
</Select>
</FormControl>
</Box>
</DialogContent>
<DialogActions>
<Button onClick={handleActionButtonClick}>Cancel</Button>
<Button onClick={handleActionButtonClick}>Ok</Button>
</DialogActions>
</Dialog>
</div>
);
}
```
## Grouping
Display categories with the `ListSubheader` component or the native `<optgroup>` element.
```tsx
import * as React from 'react';
import InputLabel from '@mui/material/InputLabel';
import MenuItem from '@mui/material/MenuItem';
import ListSubheader from '@mui/material/ListSubheader';
import FormControl from '@mui/material/FormControl';
import Select from '@mui/material/Select';
export default function GroupedSelect() {
const nativeId = React.useId();
const id = React.useId();
return (
<div>
<FormControl sx={{ m: 1, minWidth: 120 }}>
<InputLabel htmlFor={`${nativeId}-select`}>Grouping</InputLabel>
<Select native defaultValue="" id={`${nativeId}-select`} label="Grouping">
<option aria-label="None" value="" />
<optgroup label="Category 1">
<option value={1}>Option 1</option>
<option value={2}>Option 2</option>
</optgroup>
<optgroup label="Category 2">
<option value={3}>Option 3</option>
<option value={4}>Option 4</option>
</optgroup>
</Select>
</FormControl>
<FormControl sx={{ m: 1, minWidth: 120 }}>
<InputLabel id={`${id}-label`}>Grouping</InputLabel>
<Select
defaultValue=""
id={`${id}-select`}
label="Grouping"
SelectDisplayProps={{
'aria-labelledby': `${id}-label`,
}}
>
<MenuItem value="">
<em>None</em>
</MenuItem>
<ListSubheader>Category 1</ListSubheader>
<MenuItem value={1}>Option 1</MenuItem>
<MenuItem value={2}>Option 2</MenuItem>
<ListSubheader>Category 2</ListSubheader>
<MenuItem value={3}>Option 3</MenuItem>
<MenuItem value={4}>Option 4</MenuItem>
</Select>
</FormControl>
</div>
);
}
```
## Accessibility
To properly label your `Select` input you need an extra element with an `id` that contains a label.
That `id` needs to match the `labelId` of the `Select`, for example:
```jsx
<InputLabel id="label">Age</InputLabel>
<Select labelId="label" id="select" value="20">
<MenuItem value="10">Ten</MenuItem>
<MenuItem value="20">Twenty</MenuItem>
</Select>
```
Alternatively a `TextField` with an `id` and `label` creates the proper markup and
ids for you:
```jsx
<TextField id="select" label="Age" value="20" select>
<MenuItem value="10">Ten</MenuItem>
<MenuItem value="20">Twenty</MenuItem>
</TextField>
```
For a [native select](#native-select), you should mention a label by giving the value of the `id` attribute of the select element to the `InputLabel`'s `htmlFor` attribute:
```jsx
<InputLabel htmlFor="select">Age</InputLabel>
<NativeSelect id="select">
<option value="10">Ten</option>
<option value="20">Twenty</option>
</NativeSelect>
```
# NativeSelect API
## Demos
For examples and details on the usage of this React component, visit the component demo pages:
- [Select](https://mui.com/material-ui/react-select/)
## Import
```jsx
import NativeSelect from '@mui/material/NativeSelect';
// or
import { NativeSelect } from '@mui/material';
```
## Props
| Name | Type | Default | Required | Description |
|------|------|---------|----------|-------------|
| children | `node` | - | No | |
| classes | `object` | `{}` | No | Override or extend the styles applied to the component. |
| IconComponent | `elementType` | `ArrowDropDownIcon` | No | |
| input | `element` | `<Input />` | No | |
| inputProps | `object` | - | No | |
| onChange | `function(event: React.ChangeEvent<HTMLSelectElement>) => void` | - | No | |
| sx | `Array<func \| object \| bool> \| func \| object` | - | No | The system prop that allows defining system overrides as well as additional CSS styles. |
| value | `any` | - | No | |
| variant | `'filled' \| 'outlined' \| 'standard'` | - | No | |
> **Note**: The `ref` is forwarded to the root element (HTMLDivElement).
> Any other props supplied will be provided to the root element ([Input](https://mui.com/material-ui/api/input/)).
## Inheritance
While not explicitly documented above, the props of the [Input](https://mui.com/material-ui/api/input/) component are also available on NativeSelect.
## Theme default props
You can use `MuiNativeSelect` to change the default props of this component with the theme.
## CSS
### Rule name
| Global class | Rule name | Description |
|--------------|-----------|-------------|
| `.Mui-disabled` | - | State class applied to the select component `disabled` class. |
| `.Mui-error` | - | State class applied to the select component `error` class. |
| - | filled | Styles applied to the select component if `variant="filled"`. |
| - | icon | Styles applied to the icon component. |
| - | iconFilled | Styles applied to the icon component if `variant="filled"`. |
| - | iconOpen | Styles applied to the icon component if the popup is open. |
| - | iconOutlined | Styles applied to the icon component if `variant="outlined"`. |
| - | iconStandard | Styles applied to the icon component if `variant="standard"`. |
| - | multiple | Styles applied to the select component if `multiple={true}`. |
| - | nativeInput | Styles applied to the underlying native input component. |
| - | outlined | Styles applied to the select component if `variant="outlined"`. |
| - | root | Styles applied to the root element. |
| - | select | Styles applied to the select component `select` class. |
| - | standard | Styles applied to the select component if `variant="standard"`. |
## Source code
If you did not find the information on this page, consider having a look at the implementation of the component for more detail.
- [/packages/mui-material/src/NativeSelect/NativeSelect.js](https://github.com/mui/material-ui/tree/HEAD/packages/mui-material/src/NativeSelect/NativeSelect.js)
# Select API
## Demos
For examples and details on the usage of this React component, visit the component demo pages:
- [Select](https://mui.com/material-ui/react-select/)
## Import
```jsx
import Select from '@mui/material/Select';
// or
import { Select } from '@mui/material';
```
## Props
| Name | Type | Default | Required | Description |
|------|------|---------|----------|-------------|
| autoWidth | `bool` | `false` | No | |
| children | `node` | - | No | |
| classes | `object` | `{}` | No | Override or extend the styles applied to the component. |
| defaultOpen | `bool` | `false` | No | |
| defaultValue | `any` | - | No | |
| displayEmpty | `bool` | `false` | No | |
| IconComponent | `elementType` | `ArrowDropDownIcon` | No | |
| id | `string` | - | No | |
| input | `element` | - | No | |
| inputProps | `object` | - | No | |
| label | `node` | - | No | |
| labelId | `string` | - | No | |
| MenuProps | `object` | - | No | |
| multiple | `bool` | `false` | No | |
| native | `bool` | `false` | No | |
| onChange | `function(event: SelectChangeEvent<Value>, child?: object) => void` | - | No | |
| onClose | `function(event: object) => void` | - | No | |
| onOpen | `function(event: object) => void` | - | No | |
| open | `bool` | - | No | |
| renderValue | `function(value: any) => ReactNode` | - | No | |
| SelectDisplayProps | `object` | - | No | |
| sx | `Array<func \| object \| bool> \| func \| object` | - | No | The system prop that allows defining system overrides as well as additional CSS styles. |
| value | `'' \| any` | - | No | |
| variant | `'filled' \| 'outlined' \| 'standard'` | `'outlined'` | No | |
> **Note**: The `ref` is forwarded to the root element (HTMLDivElement).
> Any other props supplied will be provided to the root element ([OutlinedInput](https://mui.com/material-ui/api/outlined-input/)).
## Inheritance
While not explicitly documented above, the props of the [OutlinedInput](https://mui.com/material-ui/api/outlined-input/) component are also available on Select.
## Theme default props
You can use `MuiSelect` to change the default props of this component with the theme.
## CSS
### Rule name
| Global class | Rule name | Description |
|--------------|-----------|-------------|
| `.Mui-disabled` | - | State class applied to the select component `disabled` class. |
| `.Mui-error` | - | State class applied to the root element if `error={true}`. |
| - | filled | Styles applied to the select component if `variant="filled"`. |
| `.Mui-focused` | - | Styles applied to the select component if it is focused. |
| - | icon | Styles applied to the icon component. |
| - | iconOpen | Styles applied to the icon component if the popup is open. |
| - | multiple | Styles applied to the select component if `multiple={true}`. |
| - | nativeInput | Styles applied to the underlying native input component. |
| - | outlined | Styles applied to the select component if `variant="outlined"`. |
| - | root | Styles applied to the root element. |
| - | select | Styles applied to the select component `select` class. |
| - | standard | Styles applied to the select component if `variant="standard"`. |
## Source code
If you did not find the information on this page, consider having a look at the implementation of the component for more detail.
- [/packages/mui-material/src/Select/Select.js](https://github.com/mui/material-ui/tree/HEAD/packages/mui-material/src/Select/Select.js)