【问题标题】:How Can i limit the maximum number of options that can be selected in a Material UI lab Autocomplete component如何限制 Material UI 实验室自动完成组件中可以选择的最大选项数
【发布时间】:2021-03-14 00:19:46
【问题描述】:

(例如)我希望限制用户在我的自动完成组件中仅选择 3 个选项,并在 TAG Array 的长度达到 3 时禁用这些选项。 问题是 api 中没有 limitMaxNumberOfTags 选项,我无法获得任何方法来访问 Selected tags 数组{除了 limitTags,它只限制可见标签} . 类似的东西可能会有所帮助 getOptionDisabled={(options, tags) => (tags.length > 3 ? true : false)} . 到目前为止,这是我的自动完成实现

<Autocomplete
  multiple
  id="tags-outlined"
  options={students}
  getOptionLabel={(option) => option.personalInfo.firstName + ' ' + option.personalInfo.lastName}
  defaultValue={[...added]}
  onChange={(e, newVal) => setAdded([...newVal])}
  renderOption={(option, state) => {
    return (
      <Chip
        icon={
          <FaceIcon /> /*<Avatar color="primary" variant='outlined' size="small" className={classes.small}></Avatar>*/
        }
        label={option.personalInfo.firstName + ' ' + option.personalInfo.lastName}
        color="default"
        variant="outlined"
        {...state}
      />
    );
  }}
  renderTags={(options, getTagProps) =>
    options.map((option) => (
      <Chip
        icon={
          <FaceIcon /> /*<Avatar color="primary" variant='outlined' size="small" className={classes.small}></Avatar>*/
        }
        label={option.personalInfo.firstName + ' ' + option.personalInfo.lastName}
        color="primary"
        variant="outlined"
        {...getTagProps({})}
      />
    ))
  }
  filterSelectedOptions
  filterOptions={(options, state) =>
    options.filter((option) => {
      for (let i = 0; i < added.length; i++) {
        if (added[i]._id === option._id) {
          return false;
        }
      }
      return true;
    })
  }
  // --->         getOptionDisabled={(options) => (tags.length > 3 ? true : false)}
  renderInput={(params) => (
    <TextField {...params} variant="outlined" color="primary" label="Select Students" placeholder="Participant" />
  )}
/>

【问题讨论】:

    标签: reactjs autocomplete material-ui material-design


    【解决方案1】:

    最近遇到了类似的问题。这就是我最终要做的。基本上你必须直接在芯片本身上设置禁用标志,所以它会禁用文本输入,而不是芯片。所以你仍然可以删除每个芯片。

    export const AutoCompleteWithLimit: React.FC<Props> = ({
      disabled = false,
      limit = 2,
    }) => {
      const [disableInput, setDisableInput] = useState<boolean>(
        value.length >= limit
      );
    
      return (
        <Autocomplete
          // Set disabled based on input
          disabled={disabled || disableInput}
          multiple
          renderTags={(tagValue, getTagProps) =>
            tagValue.map((option, index) => (
              <Chip
                key={index}
                label={option.name}
                {...getTagProps({ index })}
                // Set disable explicitly after getTagProps
                disabled={disabled}
              />
            ))
          }
          onChange={(_event: any, newValue: any[]) => {
            // do something else
            // set the disable input
            setDisableInput(newValue.length >= limit);
          }}
        />
      );
    };
    

    【讨论】:

      【解决方案2】:

      Autocomplete 添加了getOptionDisabled 属性,可用于在选择最大选项后禁用所有未选择的选项。

      const a = ({limit = 3})=> {
          const [limitReached, setLimitReached] = useState(false);
          const [values, setValues] = useState([]);
          const onSelect = useCallback((newValues) => {
              setValues(newValues);
              setLimitReached(newValues.length >= limit);
          }, [limit]);
      
      
        const checkDisable = useCallback(option => limitReached && !values.includes(option), [limitReached, values]);
      
        return <Autocomplete
                      getOptionDisabled={checkDisable}
                      multiple
                      onChange={onSelect}
                      options={options}
                      value={values}
                  />
      }
      
      

      【讨论】:

        【解决方案3】:

        在翻阅文档以解决一些不相关的问题后,我找到了一种自行处理的解决方案。 解决方案包括

        1. 设置value = {[...myStateVariable]}
        2. 使用 onChange((event, newValue, reason)=&gt;{....}) 回调中的原因参数
                    <Autocomplete
                        multiple
                        id="tags-outlined"
                        options={students}
                        getOptionLabel={(option) => option.personalInfo.firstName+' '+option.personalInfo.lastName}
                        defaultValue={[...added]}
                        value={[...added]}
                        onChange={(e, newVal, reason)=>{
        
                            if(reason==="select-option"){
                                addChips(newVal)
                            } else if(reason==="remove-option"){
                                handleDelete(newVal)
                            }
                        }}
        

        HandleDelete 和 addChips 方法如下。

            const [added, setAdded] = useState([...added2])
        
            const handleDelete = (students)=>{
                setAdded([...students])
            }
        
            const addChips = (students)=>{
                if(added.length>= maxParticipation){
                    alert('Cannot add more participants')
                }else{
                    setAdded([...students])
                }
            }
        

        'newValue' 首先被 'onChange' 回调拦截,并在其中评估它的长度,如果长度大于限制值,则取消值更新。 (注意,导致进程中止的 onChange 只是 "reason" = 'select-option' 的那个)。 P.S-(忘记提及禁用选项查询)选项上的“禁用”属性也可以在渲染选项中进行操作,以在“newVal”达到给定长度后禁用所有选项。 [@justindra 详细给出的解决方案(禁用选项)]

        【讨论】:

          【解决方案4】:

          在渲染芯片之前,我使用slice 限制了renderTags 的最大限制

          <Autocomplete
            renderTags={(options, getTagProps) =>
              options.slice(0, 5).map((option) => (
                <Chip
                  icon={
                    <FaceIcon /> /*<Avatar color="primary" variant='outlined' size="small" className={classes.small}></Avatar>*/
                  }
                  label={option.personalInfo.firstName + ' ' + option.personalInfo.lastName}
                  color="primary"
                  variant="outlined"
                  {...getTagProps({})}
                />
              ))
            }
          />
          

          【讨论】:

            【解决方案5】:
             <Autocomplete
                              multiple
                              id="role"
                              options={rootStore.roleStore.listRole}
                              disableCloseOnSelect
                              value={rootStore.userStore.user.role}
                              onChange={(event, newValue) => {
                                setErrors({
                                  ...errors,
                                  role: Utils.validate.single(
                                    newValue,
                                    Utils.constraintsUser.role
                                  ),
                                })
                                if (newValue.length > 2) {
                                  alert("Please select max 2 labs")
                                } else {
                                  rootStore.userStore.updateUser({
                                    ...rootStore.userStore.user,
                                    role: newValue,
                                  })
                                }
                              }}
                              getOptionLabel={(option) => option.description || ""}
                              renderOption={(option, { selected }) => (
                                <React.Fragment>
                                  <Checkbox style={{ marginRight: 8 }} checked={selected} />
                                  {option.description}
                                </React.Fragment>
                              )}
                              renderInput={(params) => (
                                <TextField
                                  {...params}
                                  variant="outlined"
                                  label="Labs"
                                  placeholder="Labs"
                                />
                              )}
                            />
            

            完美的解决方案..

            【讨论】:

            • 对您更改/添加的代码或相关文档的链接的一些解释通常对作者有所帮助。
            【解决方案6】:

            我的解决方案,我认为这是最恰当的方式:

            <Autocomplete
              value={selectedTags}
              onChange={(ev, value: Tag[]) => {
                if (value.length <= 3) {
                  setSelectedTags(value);
                } else {
                  return;
                }
              }}
            />;
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2020-04-16
              • 2020-09-23
              • 2021-08-11
              • 2020-10-16
              • 1970-01-01
              • 2021-12-20
              • 2020-03-04
              • 2015-12-29
              相关资源
              最近更新 更多