Reputation: 203
If I use a TextField component, and set InputLabelProps={{shrink: true}}, the Label stays at the top of the TextField, and the outline is cut to show the Label correctly.
However, if I use Select component, as follows :
<FormControl variant={ this.props.variant } className={ classes.formControl } fullWidth>
<InputLabel
ref={ (input) =>{ this.inputLabel = input }}
htmlFor={ this.props.id }
shrink={ true }>
{ this.props.label }
</InputLabel>
<Select
id={ this.props.id }
value={ this.props.value }
onChange={ this.onChange }
input={
<OutlinedInput
labelWidth={ this.state.labelWidth }
name={ this.props.id }
id={ this.props.id }
/>
}
>
{ this.props.options.map(option => (
<MenuItem key={ option.value } value={ option.value }>
<em>{ option.label }</em>
</MenuItem>
))}
</Select>
</FormControl>
The Label stays at the top of the outline just like TextField, however, the outline is not cut out to display the Label nicely, instead it looks like it is "crossed out"
What am I doing wrong? (Please not, that the this.state.labelWidth has a correct value, even if I hard code this, it still does not work)
Thanks in advance for your help Cheers Jason
Upvotes: 18
Views: 24418
Reputation: 1
hope this helps :)
<FormControl fullWidth>
<InputLabel shrink>Label</InputLabel>
<Select label="Label" defaultValue={undefined} notched>
<MenuItem value="1">One</MenuItem>
<MenuItem value="2">Two</MenuItem>
</Select>
</FormControl>
<TextField
label="Label"
slotProps={{
inputLabel: {
shrink: true,
},
}}
/>
https://stackblitz.com/edit/vitejs-vite-jsxsscjo?file=src%2FApp.tsx
Upvotes: 0
Reputation: 41
To work correctly without cutting the label you must use the InputLabel component, reference it in the labelId of the Select component and repeat the Select label in the Select parameter.
See below:
<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>
Note that the select label "Age" is inside the InputLabel component and is repeated in the Select label property.
See the docs: https://mui.com/material-ui/react-select/
Upvotes: 0
Reputation: 81106
The default behavior is for the shrink
property of InputLabel
to be automatically managed by Material-UI. Generally shrink
is only applied when the Select
has a non-empty value or when it has focus. If you want to have shrink
applied all the time, then you also need to specify notched
on OutlinedInput
(in v4, on Select
for v5) since that is what controls leaving a space for the label along the outline.
The v4 code below (v5 example further down) shows both cases (1. always apply shrink
and notched
, 2. let MUI manage shrink
and notched
):
import React from "react";
import { makeStyles } from "@material-ui/core/styles";
import OutlinedInput from "@material-ui/core/OutlinedInput";
import InputLabel from "@material-ui/core/InputLabel";
import MenuItem from "@material-ui/core/MenuItem";
import FormControl from "@material-ui/core/FormControl";
import Select from "@material-ui/core/Select";
const useStyles = makeStyles(theme => ({
root: {
display: "flex",
flexWrap: "wrap"
},
formControl: {
margin: theme.spacing(1),
minWidth: 120
},
selectEmpty: {
marginTop: theme.spacing(2)
}
}));
function SimpleSelect() {
const classes = useStyles();
const [values, setValues] = React.useState({
age: ""
});
const inputLabel = React.useRef(null);
const [labelWidth, setLabelWidth] = React.useState(0);
React.useEffect(() => {
setLabelWidth(inputLabel.current.offsetWidth);
}, []);
function handleChange(event) {
setValues(oldValues => ({
...oldValues,
[event.target.name]: event.target.value
}));
}
return (
<form className={classes.root} autoComplete="off">
<FormControl variant="outlined" className={classes.formControl}>
<InputLabel
shrink
ref={inputLabel}
htmlFor="outlined-age-always-notched"
>
Age
</InputLabel>
<Select
value={values.age}
onChange={handleChange}
input={
<OutlinedInput
notched
labelWidth={labelWidth}
name="age"
id="outlined-age-always-notched"
/>
}
>
<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="outlined" className={classes.formControl}>
<InputLabel ref={inputLabel} htmlFor="outlined-age-simple">
Age
</InputLabel>
<Select
value={values.age}
onChange={handleChange}
input={
<OutlinedInput
labelWidth={labelWidth}
name="age"
id="outlined-age-simple"
/>
}
>
<MenuItem value="">
<em>None</em>
</MenuItem>
<MenuItem value={10}>Ten</MenuItem>
<MenuItem value={20}>Twenty</MenuItem>
<MenuItem value={30}>Thirty</MenuItem>
</Select>
</FormControl>
</form>
);
}
export default SimpleSelect;
Here's a similar v5 example which is simpler due to not needing to specify the input
component explicitly:
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 BasicSelect() {
const [age, setAge] = React.useState("");
const handleChange = (event: SelectChangeEvent) => {
setAge(event.target.value as string);
};
return (
<>
<FormControl sx={{ minWidth: 120, margin: 1 }}>
<InputLabel shrink id="demo-simple-select-label">
Age
</InputLabel>
<Select
notched
labelId="demo-simple-select-label"
id="demo-simple-select"
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>
<FormControl sx={{ minWidth: 120, margin: 1 }}>
<InputLabel id="demo-simple-select-label2">Age</InputLabel>
<Select
labelId="demo-simple-select-label2"
id="demo-simple-select2"
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>
</>
);
}
Upvotes: 27
Reputation: 1233
Last answer has a deprecated prop labelWidth
For the newer MUI just add shrink
prop to InputLabel component and notched
prop to Select component.
More on the issue and solution here. https://github.com/mui/material-ui/issues/22799
Upvotes: 9