vincentsty
vincentsty

Reputation: 3221

Handling formik form when validation error occurs

I have a formik form in react native code as follow. Full runnable link can be view at: here

Current behaviour:
Validation can only be done with handleSubmit, with cannot be use for handle further action. Note than onSubmit will not be trigger if handleSubmit detects there is any validation error.

 <Button onPress={handleSubmit} style={styles.button}>
     Submit
 </Button>

Expected solution:
A lifecycle event called when validation fails after an attempted submit (eg: onValidationError), where i can access all the input validation error props for further action.

Eg: I would like to handle something (like pop up an alert or scroll to first error message when validation fail)

The code is expected to be something like follow, or any other way of doing it can also be accepted. As long as i can handle event when validation error occurs.

 <Formik
    onSubmit={values => {
       alert(JSON.stringify(values, null, 2));
       Keyboard.dismiss();
    }}
    onValidationError={errorValues => {
       // any action here
       // note that onValidationError is not a built in function
       // but it would be best if it can be achieved this way
       // else any other equivalent solution also can be accepted
    }}
    validationSchema={validationSchema}>

What have tried?
I have tried to integrated 2 solution here. But failed to get it work.
https://github.com/jaredpalmer/formik/issues/1019
https://github.com/jaredpalmer/formik/issues/1484

Upvotes: 12

Views: 23983

Answers (8)

Brock
Brock

Reputation: 1645

If you are using Formik via useFormik hook you have a formik instance object you can access inside your component. This way you can put a useEffect to listen to formik.isValid change. Serves a callback role very nicely:

const formik = useFormik({
  initialValues: {}
})

useEffect(() => {
  onValidationChange(formik.isValid)
}, [formik.isValid, onValidationChange])

Upvotes: 0

Meet Makwana
Meet Makwana

Reputation: 41

Try this, Worked Well For me

<Formik
                    initialValues={params}
                    onSubmit={formHandler}
                    validationSchema={validationSchema}
                    innerRef={checkOutDetails}
                    enableReinitialize
                >
                    {({ submitCount, errors, values, isValidating, isSubmitting, isValid }) => (
                        <>
                            {!isValid &&
                                !isValidating &&
                                isSubmitting &&
                                setTimeout(() => {
                                    toast.error(
                                        'The information is incomplete; please review all red fields and re-submit.'
                                    );
                                }, 300)}
                            <Form>
                               //Your form fields
                            </Form>

                        </>
                     )}
      </Formik>

Upvotes: 0

Ahmet Firat Keler
Ahmet Firat Keler

Reputation: 4021

If you did not use <Formik> component and instead you used a component such as <Form> from reactstrap library with useFormik hook, you can check it out where you call formik's handleSubmit event like that

const formik = useFormik({
  initialValues : initialValues,
  onSubmit: (values) => {
  },
  validationSchema: validationSchema
});
if (formik.isValid)
  formik.handleSubmit()
else alert('Please fill in all fields!')

Upvotes: 0

user1086985
user1086985

Reputation:

Showing a notification on failed form submission can be achieved with a custom component using useFormikContext:

import { useFormikContext } from 'formik'
import { useEffect } from 'react'

const FormErrorNotification = () => {
    const { isValid, isValidating, isSubmitting } = useFormikContext()

    useEffect(() => {
        if (!isValid && !isValidating && isSubmitting) {
            alert('Fix your form errors!')
        }
    }, [isSubmitting, isValid, isValidating])

    return null
}

export default FormErrorNotification

And use it like so:

<Formik ...>
    <FormErrorNotification />
    ...
</Formik>

Upvotes: 4

there was pretty simple way to do that.

On your submit buttons onClick Method you can define a method like this;

<button onClick={() => scrollToErrors(errors)} > //errors param is formik's errors param.

https://formik.org/docs/guides/validation#validationschema

const scrollToErrors = (errors) => {
    const errorKeys = Object.keys(errors);
    if (errorKeys.length > 0) {
      document.getElementsByName(errorKeys[0])[0].focus();
    }  
 }

Upvotes: 1

zero
zero

Reputation: 1107

You can use the validate method to accomplish this. Just make sure you return the error object, so the form can handle the validation.

  <Formik
    onSubmit={async values => {
      console.log('submit', values)
    }}
    validate={values => {
      const errors = {}
     
      // Check the values object, and add custom validation 

      return errors
    }}
  ></Formik>

Upvotes: 0

Nikhil
Nikhil

Reputation: 417

I guess the above answer can solve your issue, recenlty I have created few forms (some complex ones too), using the react hook forms library. This is better than formik and redux forms. I would suggest to try it once, easy to plug and play with lots of dynamic features and validations (including patterns as well). https://react-hook-form.com/

Upvotes: -2

Meet Zaveri
Meet Zaveri

Reputation: 3059

You can use isValid prop(from <Formik>'s render props) on <form>'s onsubmit event by bypassing your logic there as (Documentation)

<form
  onSubmit={e => {
    console.log("isValid", isValid);
    isValid
      ? handleSubmit(e)
      : alert("Handle your custom method instead here");
  }}
>

You can access isValid prop from render props on formik's

 {props => {
    const {
      values,
      touched,
      errors,
      dirty,
      isSubmitting,
      handleChange,
      handleBlur,
      handleSubmit,
      handleReset,
      isValid // add this to your code
    } = props;
    return ( ... your code );
}}

I have also made codesandbox, you can view working example here - https://codesandbox.io/s/trusting-jennings-7wq0f

Note : This is not officially mentioned on any issues on formik repository or anywhere, but this is custom way intercept submit action on <form>'s onsubmit event

Hope this was helpful!

Upvotes: 16

Related Questions