wolf_math
wolf_math

Reputation: 223

MUI Autocomplete remove option after selection

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

Answers (2)

NearHuscarl
NearHuscarl

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

Live Demo

Codesandbox Demo

Upvotes: 7

Imanpal Singh
Imanpal Singh

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

Related Questions