Reputation: 223
I have a Material-UI Autocomplete
component. In order to prevent the user from selecting the same element twice (it would double id numbers) I'd like the element removed from the drop down entirely.
For example, if "Shawshank Redemption" was selected, it should get added to the list and be removed from the drop down entirely but not change the JSON data.
I've tried using a filter on filterOptions
, but that doesn't seem to be working.
import React, { useState } from "react";
import TextField from "@material-ui/core/TextField";
import Autocomplete from "@material-ui/lab/Autocomplete";
import List from "@material-ui/core/List";
import ListItem from "@material-ui/core/ListItem";
import ListItemText from "@material-ui/core/ListItemText";
import HighlightOffIcon from "@material-ui/icons/HighlightOff";
import IconButton from "@material-ui/core/IconButton";
export default function Playground() {
const defaultProps = {
options: top100Films,
getOptionLabel: (option) => option.title,
filterOptions: (options, state) => {
let newOptions = [];
options.forEach((option) => {
if (option.title.includes(state.inputValue)) {
newOptions.push(option);
}
});
return newOptions.filter((movie) => !movies.includes(movie));
}
};
const [movies, setMovies] = useState([]);
const [key, setKey] = useState(0);
return (
<div style={{ width: 300 }}>
<Autocomplete
{...defaultProps}
id="select-on-focus"
renderInput={(params) => (
<TextField {...params} label="movies" margin="normal" />
)}
onChange={(e, movie) => {
if (movie) {
// this line prevents an error if no movie is selected
setMovies([...movies, movie.title]);
}
// this setKey is supposed to clear the Autocomplete component by forcing a rerender.
// Works in my project but not here.
setKey(key + 1);
}}
/>
<List>
{movies.map((movie) => (
<ListItem key={movie.title}>
<ListItemText primary={movie} />
<IconButton
key={key}
aria-label="delete"
onClick={() => {
setMovies(() => movies.filter((m) => m !== movie));
}}
>
<HighlightOffIcon />
</IconButton>
</ListItem>
))}
</List>
</div>
);
}
// Top 100 films as rated by IMDb users. http://www.imdb.com/chart/top
const top100Films = [
{ title: "The Shawshank Redemption", year: 1994 },
{ title: "The Godfather", year: 1972 },
{ title: "The Godfather: Part II", year: 1974 },
{ title: "The Dark Knight", year: 2008 },
];
See also: https://codesandbox.io/s/autocomplete-remove-from-list-5dvhg?file=/demo.js:0-6677
Edit: My project just got updated to MUI5, so I'm working on getting full functionality back, then I'll tackle this problem.
Upvotes: 5
Views: 12975
Reputation: 81290
Set Autocomplete
mode to multiple
and turn on filterSelectedOptions
to remove the selected option in the dropdown list. To display a list of selected options properly outside of the Autocomplete
input, see this other answer.
const [movies, setMovies] = useState([]);
<Autocomplete
{...defaultProps}
multiple
filterSelectedOptions
renderTags={() => null} // don't render tag in the TextField
value={movies}
onChange={(e, newValue) => setMovies(newValue)}
/>
Upvotes: 7
Reputation: 1201
In order to prevent the user from selecting the same element twice (it would double id numbers) I'd like the element removed from the drop down entirely.
How about disabling them so that they cannot be selected again?
You can pass a getOptionsDisabled
just like the getOptionLabel
Upvotes: 1