MUI 芯片作为可以选择的标签(类似复选框的行为)
MUI Chips as tags that can be selected (checkbox like behavior)
我有一个 JSON 文件,我从中获取芯片数据
[
{ "id": "4", "name": "Caucasian" },
{ "id": "5", "name": "Asian" },
{ "id": "6", "name": "Middle Eastern" },
{ "id": "7", "name": "Eurasian" },
{ "id": "8", "name": "African" },
{ "id": "10", "name": "Caribbean" },
{ "id": "11", "name": "Scandinavian European" },
{ "id": "12", "name": "Afro American" },
{ "id": "13", "name": "Latin American" },
{ "id": "14", "name": "European" },
{ "id": "15", "name": "Slavic European" },
{ "id": "16", "name": "American Indian" },
{ "id": "17", "name": "Inuit" },
{ "id": "21", "name": "Aboriginal/Torres Strait" },
{ "id": "22", "name": "Maori" },
{ "id": "23", "name": "Pacific Islander" },
{ "id": "24", "name": "Indian" },
{ "id": "26", "name": "Cambodian" },
{ "id": "27", "name": "Korean" },
{ "id": "28", "name": "Vietnamese" },
{ "id": "29", "name": "Thai" },
{ "id": "30", "name": "Chinese" },
{ "id": "31", "name": "Malaysian" },
{ "id": "32", "name": "Filipino" },
{ "id": "33", "name": "Japanese" },
{ "id": "34", "name": "Indonesian" },
{ "id": "35", "name": "Singaporean" },
{ "id": "147", "name": "Fijian" },
{ "id": "148", "name": "Tongan" },
{ "id": "150", "name": "Cook Islander" },
{ "id": "156", "name": "Northern European" },
{ "id": "157", "name": "Latin European" },
{ "id": "158", "name": "Central American" },
{ "id": "159", "name": "South American Indian" },
{ "id": "160", "name": "Hawaiian" },
{ "id": "161", "name": "East African" },
{ "id": "162", "name": "West African" },
{ "id": "163", "name": "Northern African" },
{ "id": "164", "name": "Eskimo" },
{ "id": "165", "name": "Arabic" },
{ "id": "166", "name": "Southern African" }
]
我已经将这些数据映射为 MUI 芯片
{chipData.map((c) => (
<Chip label={c.name} key={c.id} onClick={handleClick} />
))}
我需要做的是使每个筹码 select 可用,然后通过单击按钮使用自动完成功能转移所有 selected 筹码以匹配筹码 selected .
所以基本上,有两种方法可以select筹码。
- 使用自动完成(类型和 Select)
- 从一个显示所有筹码的模式中,并且能够select它就像复选框一样(点击并Select)
我试过使用 useState
,但问题是所有芯片都共享一个 useState
,所以只要一个是 selected/unselected,所有芯片都会随之而来。
我有点被困在这里,但似乎找不到与我正在尝试做的事情类似的解决方案。
任何 insight/solution 都会很有帮助!
function Chip({name, onClick, variant, children}){
return (
<div className={variant} onClick={onClick}>{children}</div>
)
}
const listOfChips = [
{ id: "4", name: "Caucasian" },
{ id: "5", name: "Asian" },
{ id: "6", name: "Middle Eastern" },
{ id: "7", name: "Eurasian" },
{ id: "8", name: "African" },
{ id: "10", name: "Caribbean" },
{ id: "11", name: "Scandinavian European" },
{ id: "12", name: "Afro American" },
{ id: "13", name: "Latin American" },
{ id: "14", name: "European" },
{ id: "15", name: "Slavic European" },
{ id: "16", name: "American Indian" },
{ id: "17", name: "Inuit" },
{ id: "21", name: "Aboriginal/Torres Strait" },
{ id: "22", name: "Maori" },
{ id: "23", name: "Pacific Islander" },
{ id: "24", name: "Indian" },
{ id: "26", name: "Cambodian" },
{ id: "27", name: "Korean" },
{ id: "28", name: "Vietnamese" },
{ id: "29", name: "Thai" },
{ id: "30", name: "Chinese" },
{ id: "31", name: "Malaysian" },
{ id: "32", name: "Filipino" },
{ id: "33", name: "Japanese" },
{ id: "34", name: "Indonesian" },
{ id: "35", name: "Singaporean" },
{ id: "147", name: "Fijian" },
{ id: "148", name: "Tongan" },
{ id: "150", name: "Cook Islander" },
{ id: "156", name: "Northern European" },
{ id: "157", name: "Latin European" },
{ id: "158", name: "Central American" },
{ id: "159", name: "South American Indian" },
{ id: "160", name: "Hawaiian" },
{ id: "161", name: "East African" },
{ id: "162", name: "West African" },
{ id: "163", name: "Northern African" },
{ id: "164", name: "Eskimo" },
{ id: "165", name: "Arabic" },
{ id: "166", name: "Southern African" },
];
function App() {
const [allChips, setAllChips] = React.useState(listOfChips);
const [selected, setSelected] = React.useState(new Set());
function handleSelectionChanged(id) {
// treat state as immutable
// React only does a shallow comparison so we need a new Set
const newSet = new Set(selected);
if (newSet.has(id)) newSet.delete(id);
else newSet.add(id);
setSelected(newSet);
}
return (
<React.Fragment>
{allChips.map((c) => (
<Chip
key={c.id}
onClick={() => handleSelectionChanged(c.id)}
variant={selected.has(c.id) ? "filled" : "outlined"}
>
{c.name}
</Chip>
))}
</React.Fragment>
);
}
ReactDOM.render(<App />, document.getElementById("root"));
div {
border-radius: 20px;
padding: 10px;
margin: 10px;
}
.filled {
background-color: black;
color: white;
border: 1px solid white;
}
.outlined {
background-color: white;
color: black;
border: 1px solid black;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script>
<div id="root"></div>
一种方法(还有其他方法)是使用 Set
,它包含所有已选择的 ID,并且根据 ID 是否在集合中,您可以进行一些条件渲染.
I have created a component chip here to show that it works you can of course use the MUI Chip and use the variant
prop, or something else of course.
每当单击 Chip
时,您只需检查它是否在集合中。如果不是,请添加它。如果是,请将其删除。
就您在输入字段中的输入而言,该方法非常简单。您需要一个输入字段,并且 onChange
您需要通过 name
搜索可能的筹码,例如使用 startsWith()
(或更高级的 auto-completion),一旦用户选择特定芯片,您将拥有该芯片的 id
并可以使用该 ID 调用 handleSelectionChanged(id)
.这当然意味着如果您键入它两次,它将再次被删除,但您当然也可以为此更改逻辑。
我有一个 JSON 文件,我从中获取芯片数据
[
{ "id": "4", "name": "Caucasian" },
{ "id": "5", "name": "Asian" },
{ "id": "6", "name": "Middle Eastern" },
{ "id": "7", "name": "Eurasian" },
{ "id": "8", "name": "African" },
{ "id": "10", "name": "Caribbean" },
{ "id": "11", "name": "Scandinavian European" },
{ "id": "12", "name": "Afro American" },
{ "id": "13", "name": "Latin American" },
{ "id": "14", "name": "European" },
{ "id": "15", "name": "Slavic European" },
{ "id": "16", "name": "American Indian" },
{ "id": "17", "name": "Inuit" },
{ "id": "21", "name": "Aboriginal/Torres Strait" },
{ "id": "22", "name": "Maori" },
{ "id": "23", "name": "Pacific Islander" },
{ "id": "24", "name": "Indian" },
{ "id": "26", "name": "Cambodian" },
{ "id": "27", "name": "Korean" },
{ "id": "28", "name": "Vietnamese" },
{ "id": "29", "name": "Thai" },
{ "id": "30", "name": "Chinese" },
{ "id": "31", "name": "Malaysian" },
{ "id": "32", "name": "Filipino" },
{ "id": "33", "name": "Japanese" },
{ "id": "34", "name": "Indonesian" },
{ "id": "35", "name": "Singaporean" },
{ "id": "147", "name": "Fijian" },
{ "id": "148", "name": "Tongan" },
{ "id": "150", "name": "Cook Islander" },
{ "id": "156", "name": "Northern European" },
{ "id": "157", "name": "Latin European" },
{ "id": "158", "name": "Central American" },
{ "id": "159", "name": "South American Indian" },
{ "id": "160", "name": "Hawaiian" },
{ "id": "161", "name": "East African" },
{ "id": "162", "name": "West African" },
{ "id": "163", "name": "Northern African" },
{ "id": "164", "name": "Eskimo" },
{ "id": "165", "name": "Arabic" },
{ "id": "166", "name": "Southern African" }
]
我已经将这些数据映射为 MUI 芯片
{chipData.map((c) => (
<Chip label={c.name} key={c.id} onClick={handleClick} />
))}
我需要做的是使每个筹码 select 可用,然后通过单击按钮使用自动完成功能转移所有 selected 筹码以匹配筹码 selected .
所以基本上,有两种方法可以select筹码。
- 使用自动完成(类型和 Select)
- 从一个显示所有筹码的模式中,并且能够select它就像复选框一样(点击并Select)
我试过使用 useState
,但问题是所有芯片都共享一个 useState
,所以只要一个是 selected/unselected,所有芯片都会随之而来。
我有点被困在这里,但似乎找不到与我正在尝试做的事情类似的解决方案。 任何 insight/solution 都会很有帮助!
function Chip({name, onClick, variant, children}){
return (
<div className={variant} onClick={onClick}>{children}</div>
)
}
const listOfChips = [
{ id: "4", name: "Caucasian" },
{ id: "5", name: "Asian" },
{ id: "6", name: "Middle Eastern" },
{ id: "7", name: "Eurasian" },
{ id: "8", name: "African" },
{ id: "10", name: "Caribbean" },
{ id: "11", name: "Scandinavian European" },
{ id: "12", name: "Afro American" },
{ id: "13", name: "Latin American" },
{ id: "14", name: "European" },
{ id: "15", name: "Slavic European" },
{ id: "16", name: "American Indian" },
{ id: "17", name: "Inuit" },
{ id: "21", name: "Aboriginal/Torres Strait" },
{ id: "22", name: "Maori" },
{ id: "23", name: "Pacific Islander" },
{ id: "24", name: "Indian" },
{ id: "26", name: "Cambodian" },
{ id: "27", name: "Korean" },
{ id: "28", name: "Vietnamese" },
{ id: "29", name: "Thai" },
{ id: "30", name: "Chinese" },
{ id: "31", name: "Malaysian" },
{ id: "32", name: "Filipino" },
{ id: "33", name: "Japanese" },
{ id: "34", name: "Indonesian" },
{ id: "35", name: "Singaporean" },
{ id: "147", name: "Fijian" },
{ id: "148", name: "Tongan" },
{ id: "150", name: "Cook Islander" },
{ id: "156", name: "Northern European" },
{ id: "157", name: "Latin European" },
{ id: "158", name: "Central American" },
{ id: "159", name: "South American Indian" },
{ id: "160", name: "Hawaiian" },
{ id: "161", name: "East African" },
{ id: "162", name: "West African" },
{ id: "163", name: "Northern African" },
{ id: "164", name: "Eskimo" },
{ id: "165", name: "Arabic" },
{ id: "166", name: "Southern African" },
];
function App() {
const [allChips, setAllChips] = React.useState(listOfChips);
const [selected, setSelected] = React.useState(new Set());
function handleSelectionChanged(id) {
// treat state as immutable
// React only does a shallow comparison so we need a new Set
const newSet = new Set(selected);
if (newSet.has(id)) newSet.delete(id);
else newSet.add(id);
setSelected(newSet);
}
return (
<React.Fragment>
{allChips.map((c) => (
<Chip
key={c.id}
onClick={() => handleSelectionChanged(c.id)}
variant={selected.has(c.id) ? "filled" : "outlined"}
>
{c.name}
</Chip>
))}
</React.Fragment>
);
}
ReactDOM.render(<App />, document.getElementById("root"));
div {
border-radius: 20px;
padding: 10px;
margin: 10px;
}
.filled {
background-color: black;
color: white;
border: 1px solid white;
}
.outlined {
background-color: white;
color: black;
border: 1px solid black;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script>
<div id="root"></div>
一种方法(还有其他方法)是使用 Set
,它包含所有已选择的 ID,并且根据 ID 是否在集合中,您可以进行一些条件渲染.
I have created a component chip here to show that it works you can of course use the MUI Chip and use the
variant
prop, or something else of course.
每当单击 Chip
时,您只需检查它是否在集合中。如果不是,请添加它。如果是,请将其删除。
就您在输入字段中的输入而言,该方法非常简单。您需要一个输入字段,并且 onChange
您需要通过 name
搜索可能的筹码,例如使用 startsWith()
(或更高级的 auto-completion),一旦用户选择特定芯片,您将拥有该芯片的 id
并可以使用该 ID 调用 handleSelectionChanged(id)
.这当然意味着如果您键入它两次,它将再次被删除,但您当然也可以为此更改逻辑。