如何在 material-ui/SelectField 组件中启用 select 所有功能?
How to enable select all feature in material-ui/SelectField component?
Document Link
我正在按照上述文档 Link 来实现 Select-field 组件。
我没有在这个组件中找到 select all 的正确文档。
组件的导入语句
import SelectField from 'material-ui/SelectField';
组件代码:
<SelectField
className="search_items"
multiple={true}
hintText="Select Item"
value={values}
onChange={this.handleChange} >
{this.menuItems(values)}
</SelectField>
菜单项功能:
menuItems(values) {
return unique && unique.map((name) => (
<MenuItem
key={name}
insetChildren={true}
checked={values && values.indexOf(name) > -1}
value={name}
primaryText={name && name.concat('(').concat(sectors.filter(i => i === name).length).concat(')')}
/>
));
}
OnChange 函数:
handleChange(event, index, values) {
this.setState({ values })
}
如何为要 select 编辑的所有项目启用 select 所有选项。
提前致谢
在所有选项之上创建一个MenuItem
。
<SelectField
multiple={true}
hintText="Multiple Select"
value={values}
onChange={this.handleChange}
>
<MenuItem
checked={this.state.open}
value="Select all"
onClick={this.selectAll}
primaryText={checkedAll?"Select None":"Select all"}
/>
{this.menuItems(values)}
</SelectField>
创建一个状态 checkedAll
,只要单击 Select All
项,该状态就会更新。每当单击 SelectAll
MenuItem 时,都会使用函数将值更新为所需的数据(此处是唯一的)。
selectAll = () => {
if(this.state.checkedAll)
this.setState(
{values:[]}
);
else
this.setState(
{values:names}
);
this.setState({
checkedAll:!this.state.checkedAll
});
}
如评论所述,已接受的答案不再有效。这仍然是一个好方法,但您必须从 MUI Select
组件中删除 multiple
选项,并在 Select
上实现一个 handleChange
来处理单个项目 added/removed 来自列表。
<Select
className="search_items"
hintText="Select Item"
value={values}
onChange={handleChange}
>
<MenuItem
value="all"
/>
{this.menuItems(values)}
</SelectField>
const handleChange = selection => {
if (selection === "all") {
if (selected.length === options.length) {
setSelected([]);
} else {
setSelected(options);
}
} else {
let newSelected;
if (selected.map(s => s.id).includes(selection.id)) {
newSelected = selected.filter(s => s.id !== selection.id);
} else {
newSelected = [...selected, selection];
}
setSelected(newSelected);
}
};
建议的答案来自于 hooks 之前,所以我没有完全更新它,但你明白了。
我设法使接受的答案运行良好。所以在阅读本文之前请参考anonymous_siva的回答
所以是的,您不能让组件处理事件而不会产生令人不快的副作用。但是您可以使用这样的事件将事件处理从子对象中移除:
<MenuItem key={'Select all'}>
<ListItemText
primary="Select all"
onClick={(event) => {
event.stopPropagation();
setValues(values);
}}
/>
</MenuItem>
在这里您可以看到我们需要停止传播并使用所有可用的默认选项更新组件的状态。
您可以完全相同地取消选择所有选项,但将状态更改为空。
现在,您需要手动将 MenuItem 的边距和填充覆盖为零,并使用填充使子组件占据所需的位置。这将确保子级占据父级的所有内部。
使用 multiple
属性 和一个选项 Select All
以及其他选项创建一个 Select
。
与单个 selection 一样,您可以通过在 onChange
回调中访问 event.target.value
来提取新值。它始终是一个数组。单击 Select All
时,值 all
(在此示例中)将出现在数组的最后一个索引中,可用于切换 select all 或 unselect所有选项。
*此示例在选项中有一个复选框前缀。
这是 link 到 working demo in codesandbox。
const [selected, setSelected] = useState([]);
const handleChange = (event) => {
const value = event.target.value;
if (value[value.length - 1] === "all") {
setSelected(selected.length === options.length ? [] : options);
return;
}
setSelected(value);
};
<Select
multiple
value={selected}
onChange={handleChange}
renderValue={(selected) => selected.join(", ")}
>
<MenuItem value="all">
<ListItemIcon>
<Checkbox
checked={options.length > 0 && selected.length === options.length}
indeterminate={selected.length > 0 && selected.length < options.length}
/>
</ListItemIcon>
<ListItemText primary="Select All" />
</MenuItem>
{options.map((option) => (
<MenuItem key={option} value={option}>
<ListItemIcon>
<Checkbox checked={selected.indexOf(option) > -1} />
</ListItemIcon>
<ListItemText primary={option} />
</MenuItem>
))}
</Select>
@Bhalahariharan V 的解决方案很好,但没有考虑具有值 all
的输入。因此,最好在 Select all
菜单项中添加 属性 data-button-all
。
然后,在 handle change
函数中,检查这个 属性 以了解 select all
按钮是否被按下。
const [selected, setSelected] = useState([]);
const handleChange = (event) => {
const value = event.target.value.filter((val) => !!val);
const isClickAll = !!(event.currentTarget as any).getAttribute('data-button-all');
if (isClickAll) {
setSelected(selected.length === options.length ? [] : options);
return;
}
setSelected(value);
};
<Select
multiple
value={selected}
onChange={handleChange}
renderValue={(selected) => selected.join(", ")}
>
<MenuItem data-button-all>
<ListItemIcon>
<Checkbox
checked={options.length > 0 && selected.length === options.length}
indeterminate={selected.length > 0 && selected.length < options.length}
/>
</ListItemIcon>
<ListItemText primary="Select All" />
</MenuItem>
{options.map((option) => (
<MenuItem key={option} value={option}>
<ListItemIcon>
<Checkbox checked={selected.indexOf(option) > -1} />
</ListItemIcon>
<ListItemText primary={option} />
</MenuItem>
))}
</Select>
Document Link 我正在按照上述文档 Link 来实现 Select-field 组件。 我没有在这个组件中找到 select all 的正确文档。
组件的导入语句
import SelectField from 'material-ui/SelectField';
组件代码:
<SelectField
className="search_items"
multiple={true}
hintText="Select Item"
value={values}
onChange={this.handleChange} >
{this.menuItems(values)}
</SelectField>
菜单项功能:
menuItems(values) {
return unique && unique.map((name) => (
<MenuItem
key={name}
insetChildren={true}
checked={values && values.indexOf(name) > -1}
value={name}
primaryText={name && name.concat('(').concat(sectors.filter(i => i === name).length).concat(')')}
/>
));
}
OnChange 函数:
handleChange(event, index, values) {
this.setState({ values })
}
如何为要 select 编辑的所有项目启用 select 所有选项。 提前致谢
在所有选项之上创建一个MenuItem
。
<SelectField
multiple={true}
hintText="Multiple Select"
value={values}
onChange={this.handleChange}
>
<MenuItem
checked={this.state.open}
value="Select all"
onClick={this.selectAll}
primaryText={checkedAll?"Select None":"Select all"}
/>
{this.menuItems(values)}
</SelectField>
创建一个状态 checkedAll
,只要单击 Select All
项,该状态就会更新。每当单击 SelectAll
MenuItem 时,都会使用函数将值更新为所需的数据(此处是唯一的)。
selectAll = () => {
if(this.state.checkedAll)
this.setState(
{values:[]}
);
else
this.setState(
{values:names}
);
this.setState({
checkedAll:!this.state.checkedAll
});
}
如评论所述,已接受的答案不再有效。这仍然是一个好方法,但您必须从 MUI Select
组件中删除 multiple
选项,并在 Select
上实现一个 handleChange
来处理单个项目 added/removed 来自列表。
<Select
className="search_items"
hintText="Select Item"
value={values}
onChange={handleChange}
>
<MenuItem
value="all"
/>
{this.menuItems(values)}
</SelectField>
const handleChange = selection => {
if (selection === "all") {
if (selected.length === options.length) {
setSelected([]);
} else {
setSelected(options);
}
} else {
let newSelected;
if (selected.map(s => s.id).includes(selection.id)) {
newSelected = selected.filter(s => s.id !== selection.id);
} else {
newSelected = [...selected, selection];
}
setSelected(newSelected);
}
};
建议的答案来自于 hooks 之前,所以我没有完全更新它,但你明白了。
我设法使接受的答案运行良好。所以在阅读本文之前请参考anonymous_siva的回答
所以是的,您不能让组件处理事件而不会产生令人不快的副作用。但是您可以使用这样的事件将事件处理从子对象中移除:
<MenuItem key={'Select all'}>
<ListItemText
primary="Select all"
onClick={(event) => {
event.stopPropagation();
setValues(values);
}}
/>
</MenuItem>
在这里您可以看到我们需要停止传播并使用所有可用的默认选项更新组件的状态。
您可以完全相同地取消选择所有选项,但将状态更改为空。
现在,您需要手动将 MenuItem 的边距和填充覆盖为零,并使用填充使子组件占据所需的位置。这将确保子级占据父级的所有内部。
使用 multiple
属性 和一个选项 Select All
以及其他选项创建一个 Select
。
与单个 selection 一样,您可以通过在 onChange
回调中访问 event.target.value
来提取新值。它始终是一个数组。单击 Select All
时,值 all
(在此示例中)将出现在数组的最后一个索引中,可用于切换 select all 或 unselect所有选项。
*此示例在选项中有一个复选框前缀。
这是 link 到 working demo in codesandbox。
const [selected, setSelected] = useState([]);
const handleChange = (event) => {
const value = event.target.value;
if (value[value.length - 1] === "all") {
setSelected(selected.length === options.length ? [] : options);
return;
}
setSelected(value);
};
<Select
multiple
value={selected}
onChange={handleChange}
renderValue={(selected) => selected.join(", ")}
>
<MenuItem value="all">
<ListItemIcon>
<Checkbox
checked={options.length > 0 && selected.length === options.length}
indeterminate={selected.length > 0 && selected.length < options.length}
/>
</ListItemIcon>
<ListItemText primary="Select All" />
</MenuItem>
{options.map((option) => (
<MenuItem key={option} value={option}>
<ListItemIcon>
<Checkbox checked={selected.indexOf(option) > -1} />
</ListItemIcon>
<ListItemText primary={option} />
</MenuItem>
))}
</Select>
@Bhalahariharan V 的解决方案很好,但没有考虑具有值 all
的输入。因此,最好在 Select all
菜单项中添加 属性 data-button-all
。
然后,在 handle change
函数中,检查这个 属性 以了解 select all
按钮是否被按下。
const [selected, setSelected] = useState([]);
const handleChange = (event) => {
const value = event.target.value.filter((val) => !!val);
const isClickAll = !!(event.currentTarget as any).getAttribute('data-button-all');
if (isClickAll) {
setSelected(selected.length === options.length ? [] : options);
return;
}
setSelected(value);
};
<Select
multiple
value={selected}
onChange={handleChange}
renderValue={(selected) => selected.join(", ")}
>
<MenuItem data-button-all>
<ListItemIcon>
<Checkbox
checked={options.length > 0 && selected.length === options.length}
indeterminate={selected.length > 0 && selected.length < options.length}
/>
</ListItemIcon>
<ListItemText primary="Select All" />
</MenuItem>
{options.map((option) => (
<MenuItem key={option} value={option}>
<ListItemIcon>
<Checkbox checked={selected.indexOf(option) > -1} />
</ListItemIcon>
<ListItemText primary={option} />
</MenuItem>
))}
</Select>