使用 React Material-UI 自动完成始终显示默认选项
Posted
技术标签:
【中文标题】使用 React Material-UI 自动完成始终显示默认选项【英文标题】:Always Display Default Option with React Material-UI Autocomplete 【发布时间】:2021-11-17 08:36:57 【问题描述】:我在 React 中使用 Material-UI Autocomplete
进行地址搜索/验证表单,并且我希望始终有一个默认选项,无论结果如何。
在 Angular 中,我使用 [displayWith] 和一个函数来告诉它始终显示具有特定 ID 的数组中的项目,但我不确定如何在 React 中执行此操作。我一直试图找出filterOptions
,但我不希望它根据与输入相关的任何内容进行过滤,我只是希望它始终是一个选项。
在这个简化的示例中,如果我希望它始终显示带有年份的电影:1111,我该怎么做?
import React, useState, ChangeEvent from 'react';
import
TextField,
InputAdornment
from "@material-ui/core";
import Autocomplete from '@material-ui/lab/Autocomplete';
import Search from "@material-ui/icons";
import axios from "axios";
const AddressSearch = (props) =>
const [addressesList, setAddressesList] = useState([]);
const [inputAddress, setInputAddress] = useState<string>("");
const handleAddressChange = (event: ChangeEvent< value: unknown >) =>
setInputAddress(event.target.value as string);
;
const topFilms = [
title: 'I HATE MOVIES', year: 1111 ,
title: 'The Shawshank Redemption', year: 1994 ,
title: 'The Godfather',
title: 'The Godfather: Part II', year: 1974
]
return (
<div>
<Autocomplete
id="address-autocomplete"
freeSolo
options=topFilms
getOptionLabel=(option) => option.title
popupIcon=<Search />
renderInput=(params) => <TextField
id="address-input"
...params
onChange=handleAddressChange
placeholder="Quickly find your address"
InputProps= ...params.InputProps,
startAdornment: (
<InputAdornment position="start"><Search /></InputAdornment>
)
/>
/>
</div>
);
export default AddressSearch;
注意:我正在使用的网站使用的是 Material-UI v 4.12
【问题讨论】:
【参考方案1】:您可以创建filterOptions
的包装器,而无需触及原始filterOptions
中的任何内容。只需像往常一样过滤,获取结果,看看是否有默认选项,如果没有,请重新添加:
import TextField from "@mui/material/TextField";
import Autocomplete, createFilterOptions from "@mui/material/Autocomplete";
const _filterOptions = createFilterOptions();
const filterOptions = (options, state) =>
const results = _filterOptions(options, state);
if (!results.includes(myDefaultOption))
results.unshift(myDefaultOption);
return results;
;
export default function ComboBox()
return (
<Autocomplete
filterOptions=filterOptions
options=options
sx= width: 300
renderInput=(params) => <TextField ...params label="Movie" />
/>
);
const myDefaultOption = label: "My default option", year: 1994 ;
const options = [
myDefaultOption,
...
]
现场演示
【讨论】:
【参考方案2】:编辑:根据您的评论,您想从源中获取固定值,因此我进行了一些更改。
编辑:添加您的年份:1111 示例。
CodeSandbox
...
您可以将 filterOptions Docs 添加到 Autocomplete 元素,然后将 固定值 添加到结果中。
过滤选项和来源: Link to documentation
const filterOptions = createFilterOptions(
ignoreCase: true,
ignoreAccents: true
)
const topFilms = [
title: 'Elysium', year: 2013 ,
title: 'I HATE MOVIES', year: 1111 ,
title: 'The Shawshank Redemption', year: 1994 ,
title: 'The Godfather' ,
title: 'The Godfather: Part II', year: 1974
]
addressesList 状态存储您要修复的值的标题,我从您的代码中获取了这个钩子
const [addressesList, setAddressesList] = useState([1111])
从源中取出固定值,因此它们不会重复,此过滤器只会触发一次,或者如果源或“addressesList”发生变化。
const fixedValues = useMemo(() => topFilms.filter(e => addressesList.includes(e.year)), [topFilms, addressesList])
const dynamicValues = useMemo(() => topFilms.filter(e => !addressesList.includes(e.year)), [topFilms, addressesList])
自动完成组件的变化。
<Autocomplete
filterOptions=(options, _ref) => [...fixedValues, ...filterOptions(options, _ref)]
...Other attributes
/>
最终代码:
import React, useState, ChangeEvent, useMemo from 'react'
import TextField, InputAdornment from "@material-ui/core"
import Autocomplete, createFilterOptions from '@material-ui/lab/Autocomplete'
import Search from "@material-ui/icons"
const filterOptions = createFilterOptions(
ignoreCase: true,
ignoreAccents: true
)
const topFilms = [
title: 'Elysium', year: 2013 ,
title: 'I HATE MOVIES', year: 1111 ,
title: 'The Shawshank Redemption', year: 1994 ,
title: 'The Godfather' ,
title: 'The Godfather: Part II', year: 1974
]
const AddressSearch = (props) =>
const [addressesList, setAddressesList] = useState([1111])
const [inputAddress, setInputAddress] = useState("")
const handleAddressChange = (event) =>
setInputAddress(event.target.value)
const fixedValues = useMemo(() => topFilms.filter(e => addressesList.includes(e.year)), [topFilms, addressesList])
const dynamicValues = useMemo(() => topFilms.filter(e => !addressesList.includes(e.year)), [topFilms, addressesList])
return (
<div>
<Autocomplete
id="address-autocomplete"
freeSolo
options=dynamicValues
getOptionLabel=(option) => option.title
popupIcon=<Search />
filterOptions=(options, _ref) => [...fixedValues, ...filterOptions(options, _ref)]
renderInput=(params) => <TextField
id="address-input"
...params
onChange=handleAddressChange
placeholder="Quickly find your address"
InputProps=
...params.InputProps,
startAdornment: (
<InputAdornment position="start"><Search /></InputAdornment>
)
/>
/>
</div>
)
export default AddressSearch
【讨论】:
以上是关于使用 React Material-UI 自动完成始终显示默认选项的主要内容,如果未能解决你的问题,请参考以下文章
如何在 onChange 后清除 Material-ui 中的自动完成输入?
使用 React Material-UI 自动对焦 TextField
自动完成中的 React Material UI 打开模式失去焦点