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?
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.
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)
}
/>
)}
/>
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>
);
}
}