Material ui Autocomplete press enter to create new chips
Solution 1
In case you have simple elements (not objects, just strings), and you don't really need to handle state (your autocomplete is not controlled) you can use the freeSolo
prop of the Autocomplete
.
<Autocomplete
multiple
freeSolo
id="tags-outlined"
options={["foo", "bar"]}
defaultValue={["foo", "bar"]}
renderInput={params => (
<TextField
{...params}
variant="outlined"
label="filterSelectedOptions"
placeholder="Favorites"
/>
)}
/>
In case your elements are more complex and you do need to control the element:
-
Make sure the Autocomplete tag is a controlled one (you manage to value).
-
Listen to key down event on the TextField.
-
If the code is
Enter
(e.code === 'Enter'
) - take the value of the input and push it to the list of the current values that you have. -
Make sure you also handle the
onChange
to handle the removal of elements:
Here is the code:
const [autoCompleteValue, setAutoCompleteValue] = useState(["foo", "bar"]);
return (
<Autocomplete
multiple
id="tags-outlined"
options={[]}
value={autoCompleteValue}
onChange={(e, newval, reason) => {
setAutoCompleteValue(newval);
}}
renderInput={params => (
<TextField
{...params}
variant="outlined"
label="filterSelectedOptions"
placeholder="Favorites"
onKeyDown={e => {
if (e.code === 'enter' && e.target.value) {
setAutoCompleteValue(autoCompleteValue.concat(e.target.value));
}
}}
/>
)}
/>
);
Check the live working example of both options: https://codesandbox.io/s/mui-autocomplete-create-options-on-enter-gw1jc
Solution 2
To do this, don't use the Autocomplete
element from MUI. Just use a a standard TextField
with the use of InputProps
. All you need to do is add a onKeyDown
listener to the TextField
that listens for 'Enter' and when the function is triggered, have it add to an array of Chips in the InputProps
. It might look something like this:
const [inputValue, setInputValue] = useState('');
const [chips, setChips] = useState([])
const inputChange = ({target: {value}}) => {setInputValue(value)};
const handleKeyDown = ({key}) => {
if(key === 'Enter') {
setChips([...chips, inputValue])
}
};
<TextField
fullWidth
variant="outlined"
label="Fish and Chips"
value={inputValue}
onChange={inputChange}
multiline
InputProps={{
startAdornment: chips.map((item) => (
<Chip
key={item}
label={item}
/>
)),
}}
/>
This is untested as written here, but it should work. I've done something similar in one of my apps.
Paul
Updated on June 09, 2022Comments
-
Paul almost 2 years
I wish I could do such a thing using Autocomplete of material ui: wertarbyte
That is, inserting text (string) without having a list of elements from which you must select.
Therefore the noOptions message should not appear, every time the enter key is pressed on the keyboard the text is inserted.
Link: codesandbox
Code:
import React from "react"; import Chip from "@material-ui/core/Chip"; import Autocomplete from "@material-ui/lab/Autocomplete"; import { makeStyles } from "@material-ui/core/styles"; import TextField from "@material-ui/core/TextField"; const useStyles = makeStyles(theme => ({ root: { width: 500, "& > * + *": { marginTop: theme.spacing(3) } } })); export default function Tags() { const classes = useStyles(); return ( <div className={classes.root}> <Autocomplete multiple id="tags-outlined" options={[]} defaultValue={["foo", "bar"]} //getOptionLabel={(option) => option} //defaultValue={[top100Films[13]]} //filterSelectedOptions renderInput={params => ( <TextField {...params} variant="outlined" label="filterSelectedOptions" placeholder="Favorites" /> )} /> </div> ); }