【问题标题】:How to enable select all feature in material-ui/SelectField component?如何在 material-ui/SelectField 组件中启用选择所有功能?
【发布时间】:2018-12-09 19:43:03
【问题描述】:

Document Link 我正在按照上面的文档链接来实现 Select-field 组件。 我没有在这个组件中找到适合全选的文档。

组件的导入声明

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 功能:

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 })
}

如何为所有要选择的项目启用全选选项。 提前致谢

【问题讨论】:

    标签: reactjs select material-ui multi-select


    【解决方案1】:

    使用multiple 属性和选项Select All 以及其他选项创建Select

    与单选一样,您可以通过在onChange 回调中访问event.target.value 来提取新值。它始终是一个数组。当单击Select All 时,值all(在此示例中)将出现在数组的最后一个索引中,可用于切换全选或取消全选选项。

    *这个例子在选项中有一个复选框前缀。

    这是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>
    

    【讨论】:

    • 这个解决方案在我的情况下非常有效
    【解决方案2】:

    在所有选项之上创建一个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
        });
      }

    【讨论】:

    • 当我点击全选时,第一次从值中,所有项目都没有被选中,显示没有选中,然后第二次全部被选中
    • 在 selectAll 函数中应该是 if(!this.state.checkedall) 在第一行?如果是这种情况,它会正常工作
    • Material UI - MenuItem 组件截至今天(2019 年 12 月 12 日)不支持包括 onClick 在内的事件,因此此解决方案不起作用。我发现ListItemText 有一个onClick 事件,它可以嵌套到MenuItem 组件中——如material-ui.com/components/selects/#multiple-select 所示——“标签”菜单。尽管出于某种原因,将它与 Select 组件的 onChange 事件结合会导致它的行为很有趣,并且无法从 onClick 的句柄中触发任何钩子。
    【解决方案3】:

    我设法使接受的答案运作良好。所以在阅读之前请参考anonymous_siva的回答。

    所以是的,你不能让组件处理没有不愉快副作用的事件。但是您可以通过以下事件将事件处理从子级移除:

    <MenuItem key={'Select all'}>
      <ListItemText
        primary="Select all"
        onClick={(event) => {
          event.stopPropagation();
          setValues(values);
        }}
      />
    </MenuItem>

    在这里您可以看到我们需要停止传播并使用所有可用的默认选项更新您的组件的状态。

    您可以对取消全选选项执行完全相同的操作,但将状态更改为空。

    现在,您需要手动将 MenuItem 的边距和内边距覆盖为零,并使用内边距使子组件占据它需要的位置。这将确保子代占据父代的所有内部。

    【讨论】:

      【解决方案4】:

      正如评论,接受的答案不再有效。这仍然是一个好方法,但是您必须从 MUI Select 组件中去掉 multiple 选项,并在 Select 上实现一个 handleChange 来处理从列表中添加/删除的单个项目。

      <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);
          }
        };
      

      建议的答案来自之前的钩子,所以我没有完全更新它,但你明白了。

      【讨论】:

        猜你喜欢
        • 2020-09-11
        • 2021-04-03
        • 2019-10-11
        • 1970-01-01
        • 1970-01-01
        • 2018-09-25
        • 1970-01-01
        • 2020-02-26
        • 2017-11-15
        相关资源
        最近更新 更多