Skip to content
Advertisement

Truncate value of Material UI Autocomplete (replicate Material UI Multiple Select’s truncated renderValue)

As some background

With Material UI Multiple Select, you can truncate the value shown after selection, rather than going to another line (by setting the renderValue to .join the selected options, which gives the functionality of “option A, option B, …”). The important piece here is that it adds the “…” when the selected options are too long to fit on one line, rather than expanding to the next line.

For example, the following works with Multiple Select:

// Truncated value (I DO want this, for `Autocomplete`)
<Select
  labelId="demo-mutiple-name-label"
  id="demo-mutiple-name"
  multiple
  value={personName}
  onChange={handleChange}
  input={<Input />}
  renderValue={selected => selected.join(", ")}
  MenuProps={MenuProps}
>
  {names.map(name => (
    <MenuItem
      key={name}
      value={name}
      style={getStyles(name, personName, theme)}
    >
      {name}
    </MenuItem>
  ))}
</Select>

// – VERUS –
// chips that wrap to multiple lines (DON'T want this)

<Select
  labelId="demo-mutiple-chip-label"
  id="demo-mutiple-chip"
  multiple
  value={personName}
  onChange={handleChange}
  input={<Input id="select-multiple-chip" />}
  renderValue={selected => (
    <div className={classes.chips}>
      {selected.map(value => (
        <Chip key={value} label={value} className={classes.chip} />
      ))}
    </div>
  )}
  MenuProps={MenuProps}
>
  {names.map(name => (
    <MenuItem
      key={name}
      value={name}
      style={getStyles(name, personName, theme)}
    >
      {name}
    </MenuItem>
  ))}
</Select>

enter image description here

Demo of Multiple Selects


I’m trying to replicate the functionality above with the Material UI Autocomplete

but there doesn’t seem to be an obvious way to do so.

I’ve tried several approaches:

<Autocomplete
  multiple
  id="tags-standard"
  options={top100Films}
  getOptionLabel={option => option.title}
  defaultValue={[top100Films[13]]}
  renderTags={selected => {
    console.log("selected = ", selected);
    let renderTagsValue = selected
      .map(function(elem) {
        return elem.title;
      })
      .join(", ");

    return (
      <Typography noWrap={true} color="textPrimary">
        {renderTagsValue}
      </Typography>
    );
  }}
  renderInput={params => (
    <TextField
      {...params}
      variant="standard"
      label="Multiple values"
      placeholder="Favorites"
    />
  )}
/>
  1. renderTags – Since renderValue is not an option for Autocomplete‘s, I added a .join to the renderTags, but that only creates a long string that continues to wrap to the next line
  2. disableListWrap – I hoped this would prevent anything from wrapping to the next line, but it still wraps to the next line
  3. limitTags – This doesn’t work since tags can be variable lengths. 1, 2, or 3 may fit on a line depending on which tag is selected
  4. renderTags AND Typography – same as #1, plus returning a Typography element with noWrap set to true (this is close but still not right

My closest attempt is #4, but it’s still not right. It truncates, but still wraps the placeholder text to the next line, making the textbox’s height expand vertically, rather than remaining fixed (like the demo with Multiple Select).

enter image description here Demo of closest attempt


Does anyone know how to replicate Material UI Multiple Select‘s truncated renderValue with Material UI Autocomplete?

Advertisement

Answer

I get reasonable behavior by just adding style={{ maxWidth: 360 }} to the Typography in your sandbox in order to leave room for the placeholder and some space to type.

Here’s the full code:

/* eslint-disable no-use-before-define */
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";
import Typography from "@material-ui/core/Typography";

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
        disableListWrap={true}
        disableCloseOnSelect
        id="tags-standard"
        options={top100Films}
        getOptionLabel={option => option.title}
        defaultValue={[top100Films[13]]}
        renderTags={selected => {
          console.log("selected = ", selected);
          let renderTagsValue = selected
            .map(function(elem) {
              return elem.title;
            })
            .join(", ");

          return (
            <Typography
              style={{ maxWidth: 360 }}
              noWrap={true}
              color="textPrimary"
            >
              {renderTagsValue}
            </Typography>
          );
        }}
        renderInput={params => (
          <TextField
            {...params}
            variant="standard"
            label="Multiple values"
            placeholder="Favorites"
          />
        )}
      />
    </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 },
  { title: "12 Angry Men", year: 1957 },
  { title: "Schindler's List", year: 1993 },
  { title: "Pulp Fiction", year: 1994 },
  { title: "The Lord of the Rings: The Return of the King", year: 2003 },
  { title: "The Good, the Bad and the Ugly", year: 1966 },
  { title: "Fight Club", year: 1999 },
  { title: "The Lord of the Rings: The Fellowship of the Ring", year: 2001 },
  { title: "Star Wars: Episode V - The Empire Strikes Back", year: 1980 },
  { title: "Forrest Gump", year: 1994 },
  { title: "Inception", year: 2010 },
  { title: "The Lord of the Rings: The Two Towers", year: 2002 },
  { title: "One Flew Over the Cuckoo's Nest", year: 1975 },
  { title: "Goodfellas", year: 1990 },
  { title: "The Matrix", year: 1999 },
  { title: "Seven Samurai", year: 1954 },
  { title: "Star Wars: Episode IV - A New Hope", year: 1977 },
  { title: "City of God", year: 2002 },
  { title: "Se7en", year: 1995 },
  { title: "The Silence of the Lambs", year: 1991 },
  { title: "It's a Wonderful Life", year: 1946 },
  { title: "Life Is Beautiful", year: 1997 },
  { title: "The Usual Suspects", year: 1995 },
  { title: "Léon: The Professional", year: 1994 },
  { title: "Spirited Away", year: 2001 },
  { title: "Saving Private Ryan", year: 1998 },
  { title: "Once Upon a Time in the West", year: 1968 },
  { title: "American History X", year: 1998 },
  { title: "Interstellar", year: 2014 },
  { title: "Casablanca", year: 1942 },
  { title: "City Lights", year: 1931 },
  { title: "Psycho", year: 1960 },
  { title: "The Green Mile", year: 1999 },
  { title: "The Intouchables", year: 2011 },
  { title: "Modern Times", year: 1936 },
  { title: "Raiders of the Lost Ark", year: 1981 },
  { title: "Rear Window", year: 1954 },
  { title: "The Pianist", year: 2002 },
  { title: "The Departed", year: 2006 },
  { title: "Terminator 2: Judgment Day", year: 1991 },
  { title: "Back to the Future", year: 1985 },
  { title: "Whiplash", year: 2014 },
  { title: "Gladiator", year: 2000 },
  { title: "Memento", year: 2000 },
  { title: "The Prestige", year: 2006 },
  { title: "The Lion King", year: 1994 },
  { title: "Apocalypse Now", year: 1979 },
  { title: "Alien", year: 1979 },
  { title: "Sunset Boulevard", year: 1950 },
  {
    title:
      "Dr. Strangelove or: How I Learned to Stop Worrying and Love the Bomb",
    year: 1964
  },
  { title: "The Great Dictator", year: 1940 },
  { title: "Cinema Paradiso", year: 1988 },
  { title: "The Lives of Others", year: 2006 },
  { title: "Grave of the Fireflies", year: 1988 },
  { title: "Paths of Glory", year: 1957 },
  { title: "Django Unchained", year: 2012 },
  { title: "The Shining", year: 1980 },
  { title: "WALL·E", year: 2008 },
  { title: "American Beauty", year: 1999 },
  { title: "The Dark Knight Rises", year: 2012 },
  { title: "Princess Mononoke", year: 1997 },
  { title: "Aliens", year: 1986 },
  { title: "Oldboy", year: 2003 },
  { title: "Once Upon a Time in America", year: 1984 },
  { title: "Witness for the Prosecution", year: 1957 },
  { title: "Das Boot", year: 1981 },
  { title: "Citizen Kane", year: 1941 },
  { title: "North by Northwest", year: 1959 },
  { title: "Vertigo", year: 1958 },
  { title: "Star Wars: Episode VI - Return of the Jedi", year: 1983 },
  { title: "Reservoir Dogs", year: 1992 },
  { title: "Braveheart", year: 1995 },
  { title: "M", year: 1931 },
  { title: "Requiem for a Dream", year: 2000 },
  { title: "Amélie", year: 2001 },
  { title: "A Clockwork Orange", year: 1971 },
  { title: "Like Stars on Earth", year: 2007 },
  { title: "Taxi Driver", year: 1976 },
  { title: "Lawrence of Arabia", year: 1962 },
  { title: "Double Indemnity", year: 1944 },
  { title: "Eternal Sunshine of the Spotless Mind", year: 2004 },
  { title: "Amadeus", year: 1984 },
  { title: "To Kill a Mockingbird", year: 1962 },
  { title: "Toy Story 3", year: 2010 },
  { title: "Logan", year: 2017 },
  { title: "Full Metal Jacket", year: 1987 },
  { title: "Dangal", year: 2016 },
  { title: "The Sting", year: 1973 },
  { title: "2001: A Space Odyssey", year: 1968 },
  { title: "Singin' in the Rain", year: 1952 },
  { title: "Toy Story", year: 1995 },
  { title: "Bicycle Thieves", year: 1948 },
  { title: "The Kid", year: 1921 },
  { title: "Inglourious Basterds", year: 2009 },
  { title: "Snatch", year: 2000 },
  { title: "3 Idiots", year: 2009 },
  { title: "Monty Python and the Holy Grail", year: 1975 }
];

Edit Autocomplete

User contributions licensed under: CC BY-SA
4 People found this is helpful
Advertisement