Formik: "validateForm is not a function"

Created on 31 Oct 2018  路  9Comments  路  Source: formium/formik

馃悰 Bug report

Current Behavior

I'm attempting to create a multi-page form and want to be able to run validation between each page. When attempting to do this using the manual validation method, I get the error: "validateForm is not a function"

Expected behavior

Upon clicking the button, the form should run the validation.

Reproducible example

https://codesandbox.io/s/03mo7606zw

Your environment

| Software | Version(s) |
| ---------------- | ---------- |
| Formik | 1.3.0
| React | 16.1.0
| Browser | Chrome v70
| Yarn | 1.10.1
| Operating System | Windows 10 x64

Most helpful comment

@man1cato @graysonhicks I'm not sure if this is the right way to do this, but I think I got your expected behavior by passing the validation into setTouched.

See this fork of your sandbox https://codesandbox.io/s/7o2q7164x0

All 9 comments

validateForm is not a function because Formik passes the FormikProps as a render prop.

You need to destructure the render prop to get validateForm out of it, see https://codesandbox.io/s/qlnpwqywmw for a working example.

<Formik
  initialValues={{ name: "" }}
  validationSchema={validationSchema}
>
  {({ validateForm }) => (
    <Form>
      <div>
        <div>
          <Field name="name" placeholder="Name" />
        </div>
        <ErrorMessage name="name" />
      </div>
      <button
        type="button"
        onClick={() =>
          validateForm().then(() => console.log("validated!"))
        }
      >
        Next
      </button>
    </Form>
  )}
</Formik>

See more at https://github.com/jaredpalmer/formik/blob/master/docs/api/formik.md#children-func

Ok, so while I definitely feel stupid for not catching that, why doesn't the error message for the empty name field trigger when the button is clicked?

Ok, so while I definitely feel stupid for not catching that, why doesn't the error message for the empty name field trigger when the button is clicked?

https://codesandbox.io/s/qlnpwqywmw

validateForm() returns a Promise that resolves in to an errors object. Click the button and you can see the error message in the console.

Ok, so while I definitely feel stupid for not catching that, why doesn't the error message for the empty name field trigger when the button is clicked?

https://codesandbox.io/s/qlnpwqywmw

validateForm() returns a Promise that resolves in to an errors object. Click the button and you can see the error message in the console.

Right, but isn't the whole point of this method to trigger all the ErrorMessage components in the form? At least, that's what I concluded from reading the documentation.

Ok, so while I definitely feel stupid for not catching that, why doesn't the error message for the empty name field trigger when the button is clicked?

https://codesandbox.io/s/qlnpwqywmw
validateForm() returns a Promise that resolves in to an errors object. Click the button and you can see the error message in the console.

Right, but isn't the whole point of this method to trigger all the ErrorMessage components in the form? At least, that's what I concluded from reading the documentation.

ErrorMessage components are triggered after an error occurs and the element has been touched. Click the textbox in the codesandbox I posted, type one character, then click away.

Ok, so while I definitely feel stupid for not catching that, why doesn't the error message for the empty name field trigger when the button is clicked?

https://codesandbox.io/s/qlnpwqywmw
validateForm() returns a Promise that resolves in to an errors object. Click the button and you can see the error message in the console.

Right, but isn't the whole point of this method to trigger all the ErrorMessage components in the form? At least, that's what I concluded from reading the documentation.

ErrorMessage components are triggered after an error occurs and the element has been touched. Click the textbox in the codesandbox I posted, type one character, then click away.

Right, so then it's not possible to trigger them using validateForm and I gotta figure out another solution. Thanks.

@man1cato I am working with the same issue. I feel the expected behavior is to validate in the same way as when submitting, not just a 'silent' validation that doesn't display the error messages. Did you come up with a solution you were happy with?

Right now, I am leaning towards somehow using the errors object from validateForm to manually display the error messages based on what my active step of the form is. I feel like this goes against the ease of validation using a Yup validationSchema so would love to know if anyone has a better solution.

Thanks.

@man1cato @graysonhicks I'm not sure if this is the right way to do this, but I think I got your expected behavior by passing the validation into setTouched.

See this fork of your sandbox https://codesandbox.io/s/7o2q7164x0

setFieldError('sets[0].rows[0].condition', 'condition error');
setFieldTouched('sets[0].rows[0].condition', true, false);

This is something I'm up against at the moment. I'm using nested FieldArrays (sets[] and rows[]) which I'm able to validate perfectly fine with Yup but displaying any sort of error messaging to the UI is cumbersome.

values: {
    sets: [
        {
          rows: [....]
        },
        {
         rows: [....]
        }
   ]
}

It would be great if you could do validateForm({setErrors: true}) instead of having to iterate over the error response from validateForm and setting errors and touched manually with setFieldError and setFieldTouched

Was this page helpful?
0 / 5 - 0 ratings

Related issues

green-pickle picture green-pickle  路  3Comments

PeerHartmann picture PeerHartmann  路  3Comments

Jucesr picture Jucesr  路  3Comments

jaredpalmer picture jaredpalmer  路  3Comments

jaredpalmer picture jaredpalmer  路  3Comments