web-dev-qa-db-fra.com

Formik et Material-UI

J'essaie d'utiliser Formik avec le champ de texte Material-UI. Ainsi:

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;

Je veux que Formik soit responsable de la validation et de Material-UI pour les apparences ... Je veux passer les erreurs.firstName au composant TextField mais l'erreur ne s'affiche pas correctement. Comment puis-je résoudre le problème pour qu'il soit toujours lisible? Je ne veux pas écrire mon propre composant TextField . Ou peut-être existe-t-il une autre bibliothèque populaire pour les formulaires?

3
Adam Marczyk

Comme mentionné dans les commentaires, il peut être judicieux d'implémenter des composants "wrapper", comme ils l'ont fait dans ces exemples de Formik ou de ReactFinalForm:

L'idée est la même: implémenter des composants "wrapper" personnalisés pour envelopper les composants Material-UI et mapper les accessoires des API Formik ou ReactFinalForm.

Les avantages de cette approche sont de centraliser en un seul endroit le mappage entre les deux frameworks, de manière à ne pas le répéter à chaque fois. Si l’un des frameworks introduit des changements radicaux, il vous suffit de modifier ces composants "wrapper" personnalisés.

7
Ricovitch

Je ne pense pas que vous ayez besoin d'une autre bibliothèque ou même de créer votre propre wrapper, je pense que vous devez modifier un peu votre code. 

Un problème que vous avez est que vous ne transmettez pas une fonction onChange dans le TextField Material, la valeur de formulaire de firstName est toujours null et vous obtenez toujours l'erreur, même si vous avez entré un nom . Essayez d'ajouter un nom. ou id sur votre TextField et une fonction onChange comme ceci: 

<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)
        }
    />
    )}
/>
3
needsleep

Vous pouvez essayer ceci: 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>
    );
  }
}
1
Cosmo Dai