0

I have implemented form validation with formik and react. I am using material-UI.

   <Formik
    initialValues={{ name: '' }}
    onSubmit={values => {
        console.log('submitting', values);
    }}
    validate={values => {
        alert();
        let errors = {};
        if (!values.name) {
            errors.name = 'Name is required';
        }
        return errors;
    }}>

    {({
        handleSubmit,
        handleChange,
        values,
        errors
    }) => (
            <form onSubmit={handleSubmit}>
                <div>
                    <input name="name"
                        onChange={handleChange}
                        name="name"
                        value={values.name}
                        type="text"
                        placeholder="Name">
                    </input>
                    {errors.name &&
                        <span style={{ color: "red", fontWeight: "bold" }}>
                            {errors.name}
                        </span>
                    }
                </div>
                <div>
                    <button>Submit</button>
                </div>
            </form>

        )}
</Formik>

Above code is working fine for normal input tags but it is not working for Select and TextField material widgets.

Is there a compatibility issue with material UI ? Please help.

  • Formik is not really compatible with anything that doesn't accept its props exactly as provided. I find the best method is to build my own components which accept all the Formik props and implement them using whichever elements I want within those components, and then passing them as the ```component``` prop on a `````` component. – Chris B. Nov 14 '19 at 21:06
  • @ChrisB - do you have a codesandbox or other online code snippet repo, showing some Formik-compatible components you've built? I've been [testing Formik examples online](https://codesandbox.io/s/formik-fieldarray-from-docs-1-p4chd) as I learn how to use it. (You can hopefully see my other sandboxes from that one, via my account.) Formik docs are lagging behind best practices for the hook-based v2 of Formik. – ToolmakerSteve Nov 14 '19 at 22:24

1 Answers1

0

As Chris B. commented, the solution is to wrap each desired element inside a React component that has what Formik requires. In the case of Material-UI, Gerhat on GitHub has created some of those components.

You can use those by downloading the source from the github link above. There is also a usage example there, showing how to use Gerhat's "wrapper" for a Material TextField and a Select.

In Gerhat's usage example, TextField is a component in that github repo; it isn't the Material UI TextField directly; it is a Formik-compatible "wrapper" around the Material TextField widget.

By looking at gerhat's source code, you can learn how to do the same for other Material widgets you need.


HOWEVER, gerhat's implementation may not be the easiest for a beginner to understand. Those wrappers are easy to use, but it may not be obvious from that code how to write your own wrappers for other widgets or components.

See my answer here for a discussion of Formik's <Field> and useField. Those are easier ways to "wrap" existing React components. (Not specifically Material-UI widgets, but AFAIK, you can wrap those like any other React component.)


If you do want to understand gerhat's approach, here are some comments about the code you'll see at github.

This is the source to TextField.jsx in that repo.

The "heart" of TextField.jsx, is its wrapping around Material's TextField. The generated virtual-DOM element (representing a Material TextField) is seen in these lines:

return (
    <TextField
      label={label}
      error={hasError}
      helperText={hasError ? errorText : ''}
      {...field}
      {...other}
    />
  )

See the source link above, for the details of how this is made compatible with Formik. IMHO, a fairly advanced understanding of both React and Formik is required, to understand what is being done there. This is why I mentioned Field and useField as the place to start, for writing your own "Formik-compatible wrappers".

One detail I'll mention. The implementation relies on a file index.js in the same folder as TextField.jsx, to map the default of TextField.jsx, which is FTextField, to the name TextField, which is how you refer to it in the "usage" code at the start of this answer. SO Q&A about index.js file of a React component.

index.js contents:

export { default as TextField } from './TextField'

The other two files in the TextField source folder are ".d.ts" files. See this Q&A to understand those. You don't need them unless you are using TypeScript.

ToolmakerSteve
  • 18,547
  • 14
  • 94
  • 196