24

我正在尝试将 Formik 与 Material-UI 文本字段一起使用。像这样:

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;

我希望 Formik 负责外观的验证和 Material-UI。我想将 errors.firstName 传递给 TextField 组件,但错误显示不正确。我怎样才能修复它,这样它仍然可以清楚地阅读?我不想编写自己的 TextField 组件。

4

7 回答 7

28

我认为您不需要另一个库,甚至不需要创建自己的包装器,我认为您需要稍微调整一下代码。

您遇到的一个问题是您没有在 Material TextField 中传递 onChange 函数,因此 firstName 的表单值始终为空,因此即使您输入了名称,您也总是会收到错误消息。尝试在 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)
        }
    />
    )}
/>
于 2018-09-02T17:22:38.830 回答
16

正如评论中提到的,实现“包装器”组件实际上可能是一个好主意,就像他们在 Formik 或 ReactFinalForm 的示例中所做的那样:

想法是一样的:实现自定义“包装器”组件来包装 Material-UI 组件并映射 Formik 或 ReactFinalForm API 道具。

这种方法的优点是将两个框架之间的映射集中在一个地方,这样您就不必每次都重复映射,如果其中一个框架引入了重大更改,您只需更改那些自定义的“包装器”组件。

于 2018-09-07T10:21:53.580 回答
9

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

安装:

npm install --save formik-material-fields

用法:

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>
    );
  }
}
于 2018-12-12T06:41:59.347 回答
4

在此处查看 formik 文档<Field />https ://jaredpalmer.com/formik/docs/api/field

例如,您可以使用 Material 的 OutlinedInput 来设置您的输入样式:

<Field as={OutlinedInput} />
于 2020-04-01T10:35:35.677 回答
3

您可以使用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>
于 2021-02-28T22:52:50.117 回答
1

你也可以试试这个库,它为你做了繁重的工作,并围绕 Material-UI 组件(包括<TextField />)实现了包装代码:https ://github.com/stackworx/formik-material-ui 。

安装:

yarn add formik-material-ui

在您的 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 将继续按预期处理验证,并将呈现 Material UI 组件和错误消息。文档中有其他 Mui 输入组件的其他详细信息,并有助于自定义。

于 2019-09-30T22:07:42.177 回答
1

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

于 2020-12-02T13:17:01.140 回答