简体   繁体   English

将 Material-UI 的 Autocomplete 组件与 Formik 一起使用

[英]Using Material-UI's Autocomplete component with Formik

Currently trying to use Material UI's Autocomplete component with Formik.目前正在尝试将 Material UI 的Autocomplete组件与 Formik 一起使用。 So far things like text fields and traditional selects from Material-UI play very nice with Formik.到目前为止,诸如来自 Material-UI 的文本字段和传统选择之类的东西与 Formik 配合得非常好。 Implementing Autocomplete is not the case.实现自动完成并非如此。 Formik's onChange handler doesn't seem to update the value for my city_id . Formik 的 onChange 处理程序似乎没有更新我的city_id的值。 I know Autocomplete is still not apart of Material-UI's core library but was still seeing if something like this was a possibility at the moment.我知道 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);

编辑angered-goldstine-8offj

Your problem is that handleChange won't work the way you are doing.您的问题是handleChange不会按照您的方式工作。

If you take a look at the handleChange docs :如果您查看handleChange 文档

General input change event handler.通用输入更改事件处理程序。 This will update the values[key] where key is the event-emitting input's name attribute.这将更新 values[key],其中 key 是事件发射输入的 name 属性。 If the name attribute is not present, handleChange will look for an input's id attribute.如果 name 属性不存在,handleChange 将查找输入的 id 属性。 Note: "input" here means all HTML inputs.注意:这里的“输入”是指所有 HTML 输入。

Which should work fine, but the problem is that the TextField inside Autocomplete will only trigger handleChange when you type something on it, and the value will be the text, not the id or other property you want, so you need to move handleChange to the Autocomplete .这应该可以正常工作,但问题是Autocomplete中的TextField只会在您在其上键入handleChange时触发handleChange ,并且值将是文本,而不是您想要的id或其他属性,因此您需要将handleChange移动到Autocomplete

And there is another problem, you can't use handleChange in the Autocomplete because it doesn't references the input you want and it also have different parameters from the normal onChange of the input , as you can see in the docs .还有另一个问题,您不能在Autocomplete使用handleChange ,因为它没有引用您想要的输入,并且它还具有与input的正常onChange不同的参数,如您在文档中所见。

onChange
func功能
Callback fired when the value changes.值更改时触发的回调。
Signature:签名:
function(event: object, value: any) => void
event : The event source of the callback event : 回调的事件源
value : null value :空

So what you need to do is use setFieldValue and pass it to Autocomplete like所以你需要做的是使用setFieldValue并将其传递给Autocomplete就像

onChange={(e, value) => setFieldValue("city_id", value)}

You need to pass the name of your field and what value you want to get.您需要传递您的字段名称以及您想要获取的值。

Here is a working example这是一个工作示例

@vencovsky has provided the correct answer that is still working for me with Material UI 14.10.1. @vencovsky 提供了正确的答案,该答案仍然适用于 Material UI 14.10.1。

I'm adding a bit more to it as I have my field set to required in using Yup validation.我正在添加更多内容,因为我在使用Yup验证时将我的字段设置为required

To get this to work correctly I have the following: Yup config:为了Yup正常工作,我有以下内容:是的配置:

validationSchema = {
    Yup.object().shape({
        contact: Yup.string().max(255).required('Contact is required'),
    })
}

react:反应:

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

When the user click on the Autocomplete element, it fires the onOpen which runs the Formik onBlur and marks the field as touched.当用户单击Autocomplete元素时,它会触发onOpen运行Formik onBlur并将该字段标记为已触摸。 If an item is then not picked, Formik flags the field and displays the Contact is required validation message.如果随后未选取项目,Formik 会flags该字段并显示Contact is required验证消息。

You have to add onChange = {(event, value) => handleChange(value)} in Autocomplete tag as您必须在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);

If onChange don't work you can use onInputChange as well.如果 onChange 不起作用,您也可以使用 onInputChange。

I had the same issue recently and solved.我最近遇到了同样的问题并解决了。 Sharing my experience分享我的经验

Updating formik values directly on OnChange method solved the issue直接在OnChange方法上更新 formik 值解决了这个问题

onChange={(event, value) => (formik.values.country = value!)}

Here is the full code这是完整的代码

Formik settings Formik 设置

const formik = useFormik({
    initialValues: {
      id: user.id || "",
      name: user.name || "",
      country: user.country,
      email: user.email || "",
      submit: null,
    },
    validationSchema: Yup.object({
      email: Yup.string()
        .email("Must be a valid email")
        .max(255)
        .required("Email is required"),
      name: Yup.string().max(255).required("Name is required"),
    }),
    onSubmit: async (values, helpers): Promise<void> => {
      console.log("Updating user...");
      try {
        let userData: UserDetails = {
          id: values.id,
          email: values.email,
          name: values.name,
          country: values.country,
        };
        await userApi.registerUser(userData);
        helpers.setStatus({ success: true });
        helpers.setSubmitting(false);
        toast.success("User updated!");
      } catch (err) {
        console.error(err);
        toast.error("Something went wrong!");
        helpers.setStatus({ success: false });
        helpers.setErrors({ submit: err.message });
        helpers.setSubmitting(false);
      }
    },
  });

Autocomplete自动完成

            <Autocomplete
                getOptionLabel={(option): string => option.text}
                options={countries}
                value={formik.values.country}
                defaultValue={formik.values.country}
                onChange={(event, value) => (formik.values.country = value!)}
                renderInput={(params): JSX.Element => (
                  <TextField
                    {...params}
                    fullWidth
                    label="Country"
                    name="country"
                    error={Boolean(
                      formik.touched.country && formik.errors.country
                    )}
                    helperText={formik.touched.country && formik.errors.country}
                    onBlur={formik.handleBlur}
                  />
                )}
              />

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何使用 Material-Ui 自动完成多选复选框实现 Formik 的 Field 组件? - How to implement Formik's Field component with Material-Ui Autocomplete for Multi-Select check boxes? 如何使用带有 Material-UI 的 Formik 获得价值可重用的自动完成组件 - How to get value reusable Autocomplete component using Formik with Material-UI 将 Formik 与 React 和 material-ui 的 TextField 结合使用 - Using Formik with React and material-ui's TextField Formik 和 Material-UI - Formik and Material-UI 使用 Formik 的 Material UI 的自动完成功能在下拉列表中显示不同的值,但在 formik state 中设置不同的值 - Using Material UI's Autocomplete using Formik to display different value in dropdown but set different value in formik state 最小和最大日期不适用于 formik/material-ui/datepicker 组件 - min and max date not working on formik/material-ui/datepicker component 使用带有分隔符的 material-ui 自动完成 - Using material-ui autocomplete with dividers 使用 Material-UI 和 Formik 的 React 复选框树。 REACTJS - Checkbox Tree for React using Material-UI and Formik. REACTJS 使用 Formik 和 material-ui stepper 上传文件 - File upload using Formik and material-ui stepper 从 Formik 字段中的 Material UI 组件的 AutoComplete 中不显示 InitialValues - InitialValues are not displayed in AutoComplete from Material UI component in Formik Field
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM