form icon indicating copy to clipboard operation
form copied to clipboard

Validate all fields from top-level runValidation

Open JaceHensley opened this issue 5 years ago • 10 comments

I was looking through the API docs and runValidation from useForm says it doesn't run validation for all fields but to submit a feature request for this if it's needed.

I have a multi page form so I'd like to run all form validation when the user clicks to go to the next page run all field validations and set the fields with error as touched.

Formik's top-level validate function returned an object that has a mapping from field names to their error message:

{
  'field-1': 'This field is required',
  'field-5': 'Please select at least 2 options'
}

So you would call runValidation and it returns all the errors in the form and then if you wanted to you could set meta for all the fields with errors.

const {Form, runValidation, meta} = useForm()

<Form>
  <button 
    // Make it type of "button" because I want to control back from forwards
    type="button" 
    onClick={async () => {
      // Just guessing that runValidation would have to be await-ed because of possible async validation
      const errors = await runValidation()

      const keys = Object.keys(errors)
      const hasErrors = keys.length > 0

      keys.forEach(key => {
        setFieldMeta(key, prev => ({...prev, isTouched: true}))
      })

      // Handle blocking or allowing navigation
    }}
  >
    Previous Page
  </button>
  <button type="button" onClick={...}>Next Page</button>
</Form>


JaceHensley avatar Dec 04 '19 20:12 JaceHensley

Yes, I think that would be one way to solve it. Async validation is where things existing API's in other tools are lacking, but it also allows them to be simpler. Since React Form is async by default, you would need to await the validation for each field like you said. Have you tried this yet?

tannerlinsley avatar Dec 04 '19 20:12 tannerlinsley

I haven't tried that cause the docs said runValidation didn't run the validation for each individual field just the form level validation

JaceHensley avatar Dec 04 '19 21:12 JaceHensley

This is unfortunately a fundamental down side to supporting async validation. That being said. If internally a promise.all was implemented to wait for all field level validation it would be possible.

joepuzzo avatar Dec 04 '19 21:12 joepuzzo

I think that's what formik is doing, cause their validateForm function (which is the equivalent to runValidation) always returns a promise that needs to be await-ed. I don't think that's a bad pattern.

JaceHensley avatar Dec 04 '19 22:12 JaceHensley

Remember formik is going to remove async validation tho. There is an issue out where jared palmer goes into detail

joepuzzo avatar Dec 04 '19 22:12 joepuzzo

Yeah I’ve read it. Nice opinions, but I still think it’s just a challenge that can be solved with some good API design.

tannerlinsley avatar Dec 04 '19 22:12 tannerlinsley

Totally agree. That api design is the holy grail however. Needs to be done such that it adds little to no complexity

joepuzzo avatar Dec 04 '19 22:12 joepuzzo

Sure. All I am saying is that I’m willing to find and make the trade offs required to get there. I won’t settle for just giving up on async. It’s there, people want it and expect it.

Tanner Linsley On Dec 4, 2019, 5:37 PM -0500, Joe Puzzo [email protected], wrote:

Totally agree. That api design is the holy grail however. Needs to be done such that it adds little to no complexity — You are receiving this because you commented. Reply to this email directly, view it on GitHub, or unsubscribe.

tannerlinsley avatar Dec 04 '19 22:12 tannerlinsley

Ah okay I didn't realize they were planning on removing it. If you need any help with the effort let me, happy to help :)

JaceHensley avatar Dec 04 '19 22:12 JaceHensley

I was able to sort of get around this by setting validatePristine: true in useField, and then I disable the "Next" button when useForm's canSubmit is false. So this would prevent users from progressing but it doesn't show the errors, which is fine for me for now at least :)

JaceHensley avatar Dec 05 '19 17:12 JaceHensley