如何限制 Material UI 实验室自动完成组件中可以选择的最大选项数
Posted
技术标签:
【中文标题】如何限制 Material UI 实验室自动完成组件中可以选择的最大选项数【英文标题】:How Can i limit the maximum number of options that can be selected in a Material UI lab Autocomplete component 【发布时间】: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" />
)
/>
【问题讨论】:
【参考方案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】:在翻阅文档以解决一些不相关的问题后,我找到了一种自行处理的解决方案。 解决方案包括
-
设置
value = [...myStateVariable]
使用 onChange((event, newValue, reason)=>....)
回调中的原因参数
<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;
/>;
【讨论】:
以上是关于如何限制 Material UI 实验室自动完成组件中可以选择的最大选项数的主要内容,如果未能解决你的问题,请参考以下文章
如何在 onChange 后清除 Material-ui 中的自动完成输入?
React Formik Material UI Autocomplete:如何从 localStorage 填充自动完成内部的值?
使用 React Material-UI 自动完成始终显示默认选项