简体   繁体   English

Formik 和 Material-UI

[英]Formik and Material-UI

I am trying to use Formik with Material-UI text field.我正在尝试将 Formik 与 Material-UI 文本字段一起使用。 Like so:像这样:

import TextField from '@material-ui/core/TextField';
import {
  Field,
  FieldProps,
  Form,
  Formik,
  FormikErrors,
  FormikProps
} from 'formik';
import React, { Component } from 'react';

interface IMyFormValues {
  firstName: string;
}

class CreateAgreementForm extends Component<{}> {
  public render() {
    return (
      <div>
        <h1>My Example</h1>
        <Formik
          initialValues={{ firstName: '' }}
          // tslint:disable-next-line:jsx-no-lambda
          onSubmit={(values: IMyFormValues) => alert(JSON.stringify(values))}
          // tslint:disable-next-line:jsx-no-lambda
          validate={(values: IMyFormValues) => {
            const errors: FormikErrors<IMyFormValues> = {};
            if (!values.firstName) {
              errors.firstName = 'Required';
            }
            return errors;
          }}
          // tslint:disable-next-line:jsx-no-lambda
          render={(formikBag: FormikProps<IMyFormValues>) => (
            <Form>
              <Field
                name="firstName"
                render={({ field, form }: FieldProps<IMyFormValues>) => (
                  <TextField
                    error={Boolean(
                      form.errors.firstName && form.touched.firstName
                    )}
                    helperText={
                      form.errors.firstName &&
                      form.touched.firstName &&
                      String(form.errors.firstName)
                    }
                  />
                )}
              />
            </Form>
          )}
        />
      </div>
    );
  }
}

export default CreateAgreementForm;

I want Formik to be responsible for validation and Material-UI for looks.我希望 Formik 负责外观的验证和 Material-UI。 I want to pass errors.firstName to TextField component but the error doesn't display correctly.我想将 errors.firstName 传递给 TextField 组件,但错误无法正确显示。 How can I fix it so it still will be clear to read?我该如何修复它才能让它仍然清晰可读? I don't want to write my own TextField component.我不想编写自己的 TextField 组件。

I don't think you need another library or even create your own wrapper, I think you need to tweek your code a bit.我认为您不需要另一个库,甚至不需要创建自己的包装器,我认为您需要稍微修改一下代码。

One problem you have is that you don't pass an onChange function in the Material TextField so the form value of firstName is always null and so you always get the error, even if you have entered a name.您遇到的一个问题是您没有在 Material TextField 中传递 onChange 函数,因此 firstName 的表单值始终为 null,因此即使您输入了名称,您也总是会收到错误消息。 Try adding a name or id on your TextField and an onChange function like so:尝试在您的 TextField 和一个 onChange 函数上添加一个名称或 ID,如下所示:

<Field
    validateOnBlur
    validateOnChange
    name="firstName"
    render={({ field, form }) => (
    <TextField
        name={"firstName"}
        error={
            Boolean(form.errors.firstName && form.touched.firstName)
        }
        onChange={formikBag.handleChange}
        onBlur={formikBag.handleBlur}
        helperText={
            form.errors.firstName &&
            form.touched.firstName &&
            String(form.errors.firstName)
        }
    />
    )}
/>

As mentionned in comments, it may actually be a good idea to implement "wrapper" components, like they did in this samples from Formik or ReactFinalForm :正如评论中提到的,实现“包装器”组件实际上可能是一个好主意,就像他们在来自 Formik 或 ReactFinalForm 的示例中所做的那样:

The idea is the same : implement custom "wrapper" components to wrap Material-UI components and map Formik or ReactFinalForm APIs props.想法是一样的:实现自定义“包装器”组件来包装 Material-UI 组件并映射 Formik 或 ReactFinalForm API 道具。

The advantages of this approach is to centralize in one place the mapping between the two frameworks, so that you do not repeat the mapping each time, and if one of the framework introduces breaking changes you just have to change those custom "wrapper" components.这种方法的优点是将两个框架之间的映射集中在一个地方,这样您就不会每次都重复映射,如果其中一个框架引入了破坏性更改,您只需更改那些自定义“包装器”组件。

You can try this: https://github.com/daixianceng/formik-material-fields你可以试试这个: https : //github.com/daixianceng/formik-material-fields

Installation:安装:

npm install --save formik-material-fields

Usage:用法:

import React, { Component } from 'react';
import { Formik, Form } from 'formik';
import * as Yup from 'yup';
import { FormikTextField } from 'formik-material-fields';

const validationSchema = Yup.object().shape({
  username: Yup.string().required(),
});

const initialValues = {
  username: '',
};

class MyForm extends Component {
  render() {
    return (
      <Formik
        initialValues={initialValues}
        validationSchema={validationSchema}
        onSubmit={this.props.onSubmit}
      >
        {({ isValid }) => (
          <Form autoComplete="off">
            <FormikTextField
              name="username"
              label="Username"
              margin="normal"
              fullWidth
            />
          </Form>
        )}
      </Formik>
    );
  }
}

Check out the formik docs for <Field /> here: https://jaredpalmer.com/formik/docs/api/field在此处查看<Field />的 formik 文档: https ://jaredpalmer.com/formik/docs/api/field

As an example you could use Material's OutlinedInput to style your input:例如,您可以使用 Material 的 OutlinedInput 来设置输入的样式:

<Field as={OutlinedInput} />

You can use setFieldValue method useful for creating custom input change handlers您可以使用setFieldValue方法来创建自定义输入更改处理程序

<Formik
  initialValues={{
    name: "",
  }}
  onSubmit={(values: any) => console.log(values)}
>
  {({  handleSubmit, setFieldValue }) => (
    <Form noValidate autoComplete="off" onSubmit={handleSubmit}>
      <TextField
        onChange={(event) => setFieldValue("name", event.target.value)} 
        type="text"
        label="Name"
      />
    </Form>
  )}
</Formik>

You could also try this library, which does the heavy-lifting for you and implements the wrapper code around Material-UI components (including <TextField /> ): https://github.com/stackworx/formik-material-ui .你也可以试试这个库,它为你做了繁重的工作,并围绕 Material-UI 组件(包括<TextField /> )实现了包装代码: https : //github.com/stackworx/formik-material-ui

Installation:安装:

yarn add formik-material-ui

In your Formik form component, pass the <TextField /> component as the component prop of the Formik <Field /> component.在您的 Formik 表单组件中,将<TextField />组件作为 Formik <Field />组件的组件属性传递。

import { Formik, Field, Form } from 'formik';
import { TextField } from 'formik-material-ui';

<Field
  name="email"
  label="Email"
  type="email"
  component={TextField}
/>

Formik will continue to handle the validation as expected and will render the Material UI component and error message. Formik 将继续按预期处理验证,并将呈现 Material UI 组件和错误消息。 There are additional details in the docs for other Mui input components and to aid with customization.其他 Mui 输入组件的文档中还有其他详细信息,以帮助进行自定义。

要使用material-uiformik ,您可以使用官方 formik 文档中的变体: https : //formik.org/docs/examples/with-material-ui

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

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM