MUI Select – 处理下拉菜单中的重复选项

huangapple go评论67阅读模式
英文:

MUI Select - handling duplicate option in dropdown

问题

我正在使用 MUI v5,并且有两个选项具有重复的名称。当我使用 Select 组件选择它们时,两者都会被选中。

我该如何在 MUI v5 中处理这个问题?

import * as React from "react";
import OutlinedInput from "@mui/material/OutlinedInput";
import InputLabel from "@mui/material/InputLabel";
import MenuItem from "@mui/material/MenuItem";
import FormControl from "@mui/material/FormControl";
import ListItemText from "@mui/material/ListItemText";
import Select, { SelectChangeEvent } from "@mui/material/Select";
import Checkbox from "@mui/material/Checkbox";

const ITEM_HEIGHT = 48;
const ITEM_PADDING_TOP = 8;
const MenuProps = {
  PaperProps: {
    style: {
      maxHeight: ITEM_HEIGHT * 4.5 + ITEM_PADDING_TOP,
      width: 250
    }
  }
};

const namesObj = [
  {
    id: 1,
    name: "Oliver Hansen"
  },
  {
    id: 2,
    name: "Van Henry"
  },
  {
    id: 3,
    name: "April Tucker"
  },
  {
    id: 4,
    name: "April Tucker"
  }
];

export default function MultipleSelectCheckmarks() {
  const [personName, setPersonName] = React.useState<string[]>([]);
  console.log("personName: ", personName);
  const handleChange = (event: SelectChangeEvent<typeof personName>) => {
    const {
      target: { value }
    } = event;
    setPersonName(
      // On autofill we get a stringified value.
      typeof value === "string" ? value.split(",") : value
    );
  };

  return (
    <div>
      <FormControl sx={{ m: 1, width: 300 }}>
        <InputLabel id="demo-multiple-checkbox-label">Tag</InputLabel>
        <Select
          labelId="demo-multiple-checkbox-label"
          id="demo-multiple-checkbox"
          multiple
          value={personName}
          onChange={handleChange}
          input={<OutlinedInput label="Tag" />}
          renderValue={(selected) => selected.join(", ")}
          MenuProps={MenuProps}
        >
          {namesObj.map((name) => (
            <MenuItem key={name.id} value={name.name}>
              <Checkbox checked={personName.indexOf(name.name) > -1} />
              <ListItemText primary={name.name} />
            </MenuItem>
          ))}
        </Select>
      </FormControl>
    </div>
  );
}
英文:

I am using MUI v5 and I have two options which have a duplicate name. When I select them using the Select component, both are selected.

How would I handle this in MUI v5?

import * as React from &quot;react&quot;;
import OutlinedInput from &quot;@mui/material/OutlinedInput&quot;;
import InputLabel from &quot;@mui/material/InputLabel&quot;;
import MenuItem from &quot;@mui/material/MenuItem&quot;;
import FormControl from &quot;@mui/material/FormControl&quot;;
import ListItemText from &quot;@mui/material/ListItemText&quot;;
import Select, { SelectChangeEvent } from &quot;@mui/material/Select&quot;;
import Checkbox from &quot;@mui/material/Checkbox&quot;;
const ITEM_HEIGHT = 48;
const ITEM_PADDING_TOP = 8;
const MenuProps = {
PaperProps: {
style: {
maxHeight: ITEM_HEIGHT * 4.5 + ITEM_PADDING_TOP,
width: 250
}
}
};
const namesObj = [
{
id: 1,
name: &quot;Oliver Hansen&quot;
},
{
id: 2,
name: &quot;Van Henry&quot;
},
{
id: 3,
name: &quot;April Tucker&quot;
},
{
id: 4,
name: &quot;April Tucker&quot;
}
];
export default function MultipleSelectCheckmarks() {
const [personName, setPersonName] = React.useState&lt;string[]&gt;([]);
console.log(&quot;personName: &quot;, personName);
const handleChange = (event: SelectChangeEvent&lt;typeof personName&gt;) =&gt; {
const {
target: { value }
} = event;
setPersonName(
// On autofill we get a stringified value.
typeof value === &quot;string&quot; ? value.split(&quot;,&quot;) : value
);
};
return (
&lt;div&gt;
&lt;FormControl sx={{ m: 1, width: 300 }}&gt;
&lt;InputLabel id=&quot;demo-multiple-checkbox-label&quot;&gt;Tag&lt;/InputLabel&gt;
&lt;Select
labelId=&quot;demo-multiple-checkbox-label&quot;
id=&quot;demo-multiple-checkbox&quot;
multiple
value={personName}
onChange={handleChange}
input={&lt;OutlinedInput label=&quot;Tag&quot; /&gt;}
renderValue={(selected) =&gt; selected.join(&quot;, &quot;)}
MenuProps={MenuProps}
&gt;
{namesObj.map((name) =&gt; (
&lt;MenuItem key={name.id} value={name.name}&gt;
&lt;Checkbox checked={personName.indexOf(name.name) &gt; -1} /&gt;
&lt;ListItemText primary={name.name} /&gt;
&lt;/MenuItem&gt;
))}
&lt;/Select&gt;
&lt;/FormControl&gt;
&lt;/div&gt;
);
}

https://codesandbox.io/s/priceless-spence-n79nhd?file=/demo.tsx:0-2005

答案1

得分: 2

MUI使用MenuItem组件的value属性来确定哪些选项已被选择。如果两个选项具有相同的value值,则当点击其中一个选项时,它们都将被选中。

一个可能的解决方案是,使用namesObj数组的id属性作为MenuItem组件的value值,而不是使用name属性。这样,每个选项都将有一个唯一的value值,可用于识别它。例如:

export default function MultipleSelectCheckmarks() {
  const [personName, setPersonName] = React.useState<number[]>([]);
  console.log("personName: ", personName);
  const handleChange = (event: SelectChangeEvent<typeof personName>) => {
    const {
      target: { value }
    } = event;
    setPersonName(
      typeof value === "string"
        ? value.split(",").map((item) => Number(item))
        : value
    );
  };

  return (
    <div>
      <FormControl sx={{ m: 1, width: 300 }}>
        <InputLabel id="demo-multiple-checkbox-label">Tag</InputLabel>
        <Select
          multiple
          value={personName}
          onChange={handleChange}
          input={<OutlinedInput label="Tag" />}
          renderValue={(selected) =>
            selected
              .map((id) => namesObj.find((name) => name.id === id).name)
              .join(", ")
          }
          MenuProps={MenuProps}
        >
          {namesObj.map((name) => (
            <MenuItem key={name.id} value={name.id}>
              <Checkbox checked={personName.indexOf(name.id) > -1} />
              <ListItemText primary={name.name} />
            </MenuItem>
          ))}
        </Select>
      </FormControl>
    </div>
  );
}
英文:

MUI uses the value property of the MenuItem component to determine which options are selected. If two options have the same value, they will both be selected when one of them is clicked.

One possible solution is to use the id property of the namesObj array as the value of the MenuItem component, instead of the name property. This way, each option will have a unique value that can be used to identify it. For example:

export default function MultipleSelectCheckmarks() {
const [personName, setPersonName] = React.useState&lt;number[]&gt;([]);
console.log(&quot;personName: &quot;, personName);
const handleChange = (event: SelectChangeEvent&lt;typeof personName&gt;) =&gt; {
const {
target: { value }
} = event;
setPersonName(
typeof value === &quot;string&quot;
? value.split(&quot;,&quot;).map((item) =&gt; Number(item))
: value
);
};
return (
&lt;div&gt;
&lt;FormControl sx={{ m: 1, width: 300 }}&gt;
&lt;InputLabel id=&quot;demo-multiple-checkbox-label&quot;&gt;Tag&lt;/InputLabel&gt;
&lt;Select
multiple
value={personName}
onChange={handleChange}
input={&lt;OutlinedInput label=&quot;Tag&quot; /&gt;}
renderValue={(selected) =&gt;
selected
.map((id) =&gt; namesObj.find((name) =&gt; name.id === id).name)
.join(&quot;, &quot;)
}
MenuProps={MenuProps}
&gt;
{namesObj.map((name) =&gt; (
&lt;MenuItem key={name.id} value={name.id}&gt;
&lt;Checkbox checked={personName.indexOf(name.id) &gt; -1} /&gt;
&lt;ListItemText primary={name.name} /&gt;
&lt;/MenuItem&gt;
))}
&lt;/Select&gt;
&lt;/FormControl&gt;
&lt;/div&gt;
);
}

huangapple
  • 本文由 发表于 2023年7月7日 00:58:22
  • 转载请务必保留本文链接:https://go.coder-hub.com/76631049.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定