简体   繁体   中英

Material ui Autocomplete press enter to create new chips

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>
  );
}

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:

  1. Make sure the Autocomplete tag is a controlled one (you manage to value).

  2. Listen to key down event on the TextField.

  3. If the key is enter ( keyCode === 13 ) - take the value of the input and push it to the list of the current values that you have.

  4. 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.keyCode === 13 && 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

For anyone who wants to input the current best match on enter key press (as opposed to any custom text) you can use the autoHighlight prop.

<Autocomplete
    multiple
    autoHighlight
    id="tags-outlined"
    options={["foo", "bar"]}
    defaultValue={["foo", "bar"]}
    renderInput={params => (
        <TextField
            {...params}
            variant="outlined"
            label="filterSelectedOptions"
            placeholder="Favorites"
        />
    )}
/>

To do this, don't use the Autocomplete element from MUI. Just use aa 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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM