将 Material-UI 的 Autocomplete 组件与 Formik 一起使用
Posted
技术标签:
【中文标题】将 Material-UI 的 Autocomplete 组件与 Formik 一起使用【英文标题】:Using Material-UI's Autocomplete component with Formik 【发布时间】:2020-03-31 17:07:44 【问题描述】:目前正在尝试将 Material UI 的 Autocomplete 组件与 Formik 一起使用。到目前为止,诸如文本字段和 Material-UI 中的传统选择之类的东西在 Formik 上表现得非常好。实现自动完成并非如此。 Formik 的 onChange 处理程序似乎没有更新我的 city_id
的值。我知道 Autocomplete 仍然不是 Material-UI 的核心库的一部分,但目前仍在观察这样的事情是否可行。
import React from "react";
import ReactDOM from "react-dom";
import Formik, Form from 'formik';
import TextField from '@material-ui/core/TextField';
import Autocomplete from '@material-ui/lab/Autocomplete';
import Button from '@material-ui/core/Button';
import cities from '../data/cities';
import "./styles.css";
const initialValues =
city_id: '',
;
const submit = params =>
alert(`Value for city_id is: $params.city_id`);
;
function App()
return (
<Formik
initialValues= initialValues
onSubmit= submit
>
(
handleChange,
values,
) => (
<Form>
<Autocomplete
id="city_id"
name="city_id"
options= cities
groupBy= option => option.state
getOptionLabel= option => option.name
style= width: 300
renderInput=params => (
<TextField
...params
onChange= handleChange
margin="normal"
label="Cities"
fullWidth
value= values.city_id
/>
)
/>
<Button
variant="contained"
color="primary"
type="submit"
>
Submit
</Button>
</Form>
)
</Formik>
);
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
【问题讨论】:
【参考方案1】:您的问题是 handleChange
无法按照您的方式工作。
如果你看看handleChange docs:
一般输入更改事件处理程序。这将更新 values[key] ,其中 key 是事件发射输入的名称属性。如果 name 属性不存在,handleChange 将查找输入的 id 属性。注意:这里的“输入”是指所有 html 输入。
这应该可以正常工作,但问题是Autocomplete
中的TextField
只会在您在其上键入内容时触发handleChange
,并且值将是文本,而不是id
或其他属性你想要,所以你需要将handleChange
移动到Autocomplete
。
还有一个问题,你不能在Autocomplete
中使用handleChange
,因为它没有引用你想要的输入,而且它也有不同于input
的普通onChange
的参数,正如您在docs 中看到的那样。
onChange
功能 值更改时触发回调。 签名:function(event: object, value: any) => void
event
:回调的事件源value
:null
所以你需要做的是使用setFieldValue
并将其传递给Autocomplete
就像
onChange=(e, value) => setFieldValue("city_id", value)
您需要传递您的字段名称以及您想要获取的值。
这是working example
【讨论】:
完美!谢谢! @CarlEdwards 欢迎您,请考虑投票,谢谢! 完整解释完毕! 如果我的问题被认为值得注意,请考虑支持我的问题。 另外,材料 4.7.1 中的自动完成组件上有 8 个补丁,所以如果有人在遵循 Vencovsky 的解释后仍有问题,这可能就是原因。【参考方案2】:@vencovsky 提供的正确答案仍然适用于 Material UI 14.10.1。
我在使用Yup
验证时将我的字段设置为required
,因此我要添加更多内容。
为了让它正常工作,我有以下几点:
Yup
配置:
validationSchema =
Yup.object().shape(
contact: Yup.string().max(255).required('Contact is required'),
)
反应:
<Autocomplete
id="contact-autocomplete"
options=contacts
getOptionLabel=(contact) => `$contact?.firstName $contact?.lastName`
onChange=(e, value) => setFieldValue("contact", value?.id || "")
onOpen=handleBlur
includeInputInList
renderInput=(params) => (
<TextField
...params
error=Boolean(touched.contact && errors.contact)
fullWidth
helperText=touched.contact && errors.contact
label="Contact Person"
name="contact"
variant="outlined"
/>
)
/>
当用户单击Autocomplete
元素时,它会触发onOpen
,它运行Formik
onBlur
并将该字段标记为已触摸。如果一个项目没有被拾取,Formikflags
字段并显示Contact is required
验证消息。
【讨论】:
onOpen=handleBlur
在选择期间显示“必需”错误。改用onBlur=handleBlur
会更好,因为只有在选择/清除后才会显示错误。【参考方案3】:
你必须在Autocomplete
标签中添加onChange = (event, value) => handleChange(value)
为
import React from "react";
import ReactDOM from "react-dom";
import Formik, Form from 'formik';
import TextField from '@material-ui/core/TextField';
import Autocomplete from '@material-ui/lab/Autocomplete';
import Button from '@material-ui/core/Button';
import cities from '../data/cities';
import "./styles.css";
const [cityId,setCityId]=React.useState(city_id:'');
const handleChange=(value)=>
// Here is the value is a selected option label or the new typed value
setCityId(city_id:value);
function App()
return (
<Formik
initialValues= cityId
onSubmit=() =>
alert(`Value for city_id is: $cityId.city_id`);
>
(
handleChange,
values,
) => (
<Form>
<Autocomplete
id="city_id"
name="city_id"
options= cities
groupBy= option => option.state
getOptionLabel= option => option.name
style= width: 300
onChange = (event, value) => handleChange(value)
renderInput=params => (
<TextField
...params
onChange= handleChange
margin="normal"
label="Cities"
fullWidth
value= values.city_id
/>
)
/>
<Button
variant="contained"
color="primary"
type="submit"
>
Submit
</Button>
</Form>
)
</Formik>
);
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
如果 onChange 不起作用,您也可以使用 onInputChange。
【讨论】:
以上是关于将 Material-UI 的 Autocomplete 组件与 Formik 一起使用的主要内容,如果未能解决你的问题,请参考以下文章
React & Material-UI 分页 - 将 Material-UI 的组件连接到 React-Router
Material-ui <Autocomplete /> getOptionLabel - 将空字符串作为值传递
material-ui 组件样式自定义 - 将选择组件的颜色更改为白色
Material-UI 滑块未将名称道具暴露给 Formik