2

I created a Select using React that allows the user to select multiple options. The problem is that the Select displays the ID of the selected item, instead of their name. How can I change the code in a way that the Select display the names separated by commas (now shows the IDs separated by commas), while keeping the array of ids for later processing.

Any idea how to fix it? Here is the code to CodeSanbox

I have the following array in a Material UI Select:

const names = [
  { id: "1", value: "Oliver Hansen" },
  { id: "2", value: "Van Henry" },
  { id: "3", value: "Omar Alexander" }
];

This is the code that renders the Multiple Select:

<Select
          labelId="demo-mutiple-checkbox-label"
          id="demo-mutiple-checkbox"
          multiple
          value={personName}
          name="first"
          onChange={handleChange}
          input={<OutlinedInput label="Tag" />}
          renderValue={(selected) => selected.join(", ")}
        >
          {names.map((name) => (
            <MenuItem key={name.id} value={name.id}>
              <Checkbox checked={personName.indexOf(name.id) > -1} />
              <ListItemText primary={name.value} />
            </MenuItem>
          ))}
        </Select>
1
  • You wanted to show the names, but also keep the selected names Ids as well in the state? Commented Sep 30, 2021 at 1:40

5 Answers 5

5

I found one possible solution for your issue.

check if it works for you.

import React from "react";
import { makeStyles } from "@material-ui/core/styles";
import { Input, OutlinedInput } from "@material-ui/core";
import InputLabel from "@material-ui/core/InputLabel";
import FormControl from "@material-ui/core/FormControl";
import Select from "@material-ui/core/Select";
import MenuItem from "@material-ui/core/MenuItem";
import ListItemText from "@material-ui/core/ListItemText";
import Checkbox from "@material-ui/core/Checkbox";

const useStyles = makeStyles((theme) => ({
  formControl: {
    margin: theme.spacing(1),
    minWidth: 300
  },
  selectEmpty: {
    marginTop: theme.spacing(2)
  }
}));

const names = [
  { id: "1", value: "Oliver Hansen" },
  { id: "2", value: "Van Henry" },
  { id: "3", value: "Van Henry" }
];

export default function NativeSelects() {
  const classes = useStyles();
  const [personName, setPersonName] = React.useState([]);

  const handleChange = (event) => {
    const {
      target: { value }
    } = event;
    setPersonName(
      // On autofill we get a the stringified value.
      typeof value === "string" ? value.split(",") : value
    );
  };

  return (
    <div>
      <FormControl className={classes.formControl}>
        <InputLabel htmlFor="age-native-simple">
          Names here to select from
        </InputLabel>
        <Select
          labelId="demo-mutiple-checkbox-label"
          id="demo-mutiple-checkbox"
          multiple
          value={personName}
          name="first"
          onChange={handleChange}
          input={<OutlinedInput label="Tag" />}
          renderValue={(selected) => selected.map(obj=> names[obj - 1].value).join(", ")}
        >
          {names.map((name) => (
            <MenuItem key={name.id} value={name.id}>
              <Checkbox checked={personName.indexOf(name.id) > -1} />
              <ListItemText primary={name.value} />
            </MenuItem>
          ))}
        </Select>
      </FormControl>
    </div>
  );
}

Updated Code

Sign up to request clarification or add additional context in comments.

1 Comment

Genius solution. Thank you very much!
2

just you can do this:

renderValue={
    (selected) => 
        names.filter( name => selected.includes(name.id) )
            .map( record => record.name )
            .join(", ")
} 

2 Comments

While this link may answer the question, it is better to include the essential parts of the answer here and provide the link for reference. Link-only answers can become invalid if the linked page changes. - From Review
This one helped me to render object with discrete id values.
1

To show the selected user's names, you can update the map part, where currently, you're using id.

You can update this to use the name.value to store/show the person's names.

{names.map((name) => (
   <MenuItem key={name.value} value={name.value}>
     <Checkbox checked={personName.indexOf(name.value) > -1} />
     <ListItemText primary={name.value} />
   </MenuItem>
 ))}

Updated Sandbox

3 Comments

This way might be a problem, if there is duplicate names in the array.
Exactly, I also need the IDs list for that very reason.
Yeah, in that case, this is not an optimal solution.
1

the simple steps I did, just focus on the renderValue property, on the Select component:

renderValue={(selected) => names.find((val) => val.id === selected).value}

the logic I use, find the value in the 'names' array, where the id is the selected id, then take the 'value' value in the 'names' array, to display.

Comments

0

Update the Menu Items' value to be a object instead of an id.

    <Select
      labelId="demo-mutiple-checkbox-label"
      id="demo-mutiple-checkbox"
      multiple
      value={personName}
      name="first"
      onChange={handleChange}
      input={<OutlinedInput label="Tag" />}
      renderValue={(selected) => selected.map((item) => item.value)?.join(",")}
    >
      {names.map((name) => (
        <MenuItem key={name.id} value={name}>
          <Checkbox
            checked={personName.find((p) => p.id === name.id) !== undefined}
          />
          <ListItemText primary={name.value} />
        </MenuItem>
      ))}
    </Select>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.