Briar
Briar

Reputation: 367

Material UI Autocomplete different colour tags?

I just started learning material-ui and I'm having some issues figuring out a few things.

  1. I want to have multiple arrays be included in the autocomplete menu (eg. options={top100Films, top100Shows}, but with the proper syntax of course)

  2. I want to have the tag's color be different depending on which array it was selected from (instead of being all purple like they are now)

If multiple arrays are not possible, maybe having the option.title and option.year show up seperatly in the list and be different colour tags if selected?

If anyone knows how to do this or something similar, I would really appreciate the help!

import React from "react";
import TextField from "@material-ui/core/TextField";
import Autocomplete from "@material-ui/lab/Autocomplete";
import { withStyles } from "@material-ui/core/styles";

const CustomAutocomplete = withStyles({
  tag: {
    backgroundColor: "#a0a",
    height: 24,
    position: "relative",
    zIndex: 0,
    "& .MuiChip-label": {
      color: "#fff",
    },
    "& .MuiChip-deleteIcon": {
      color: "#a0a",
    },
    "&:after": {
      content: '""',
      right: 10,
      top: 6,
      height: 12,
      width: 12,
      position: "absolute",
      backgroundColor: "white",
      zIndex: -1,
    },
  },
})(Autocomplete);

export default function Tags() {
  return (
    <div style={{ width: 500 }}>
      <CustomAutocomplete
        disableClearable="true"
        filterSelectedOptions="true"
        multiple
        id="tags-standard"
        options={final}
        getOptionSelected
        getOptionLabel={(o) => o}
        renderTags={(value, getTagProps) =>
          value.map((option, index) => (
            <Chip
              className={option.type === "film" ? "tagBlue" : "tagRed"}
              variant="outlined"
              label={`${option.title} ${option.year}`}
              {...getTagProps({ index })}
            />
          ))
        }
        renderInput={(params) => (
          <TextField
            {...params}
            variant="standard"
            placeholder="Favorites"
            margin="normal"
            fullWidth
          />
        )}
      />
    </div>
  );
}

const top100Shows = [
  { title: "Once ", year: 19 },
  { title: "Ameri", year: 1998 },
  { title: "ar", year: 2014 },
  { title: "Cas", year: 1942 },
  { title: "C", year: 1931 },
  { title: "P", year: 1960 },
  { title: "Thee", year: 1999 },
  { title: "The", year: 2011 },
  { title: "Mod", year: 1936 },
  { title: "Rai", year: 1981 },
  { title: "Rea", year: 1954 },
  { title: "The", year: 2002 },
  { title: "Tee", year: 2006 },
  { title: "Ci", year: 1988 },
  { title: "Tr", year: 2006 },
  { title: "Gra", year: 1988 },
];

// Top 100 films as rated by IMDb users. http://www.imdb.com/chart/top
const top100Films = [
  { 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: "Cinema Paradiso", year: 1988 },
  { title: "The Lives of Others", year: 2006 },
  { title: "Grave of the Fireflies", year: 1988 },
];

const final = [
  ...top100Films.map((f) => Object.assign({}, f, { type: "film" })),
  ...top100Shows.map((s) => Object.assign({}, s, { type: "show" })),
];

Upvotes: 2

Views: 4375

Answers (1)

Befeepilf
Befeepilf

Reputation: 647

The only way to provide multiple arrays containing options to the AutoComplete component is to merge them. Since you want to render different tags based on from which individual array an option came from, you have to keep track of each option's origination. You can do this by adding a type field to each movie and show object:

[
    ...top100Films.map(f => Object.assign({}, f, {type: 'film'})),
    ...top100Shows.map(s => Object.assign({}, f, {type: 'show'}))
]

Then, pass the resulting array to the options prop of your CustomAutocomplete component.

The material-ui AutoComplete component has a prop called renderTags which accepts a function that returns components rendered in place of the tags of the selected options. Here you can implement your logic for choosing a color based on the option's type field:

renderTags={(value, getTagProps) =>
    value.map((option, index) => (
        <Chip
            className={option.type === 'film' ? 'tagBlue' : 'tagRed'}
            variant="outlined"
            label={`${option.title} ${option.year}}
            {...getTagProps({ index })}
        />
    ))
}

Make sure to import the Chip component and provide a custom getOptionSelected function to the AutoComplete component to compare objects.

Edit priceless-resonance-rb386

You can find more information in the material-ui docs.

Upvotes: 5

Related Questions