Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

validateOnChange after submit #1251

Closed
lpschz opened this issue Jan 20, 2019 · 15 comments · May be fixed by #3500
Closed

validateOnChange after submit #1251

lpschz opened this issue Jan 20, 2019 · 15 comments · May be fixed by #3500

Comments

@lpschz
Copy link

lpschz commented Jan 20, 2019

🚀 Feature request

Current Behavior

validateOnChange is either true or false

Desired Behavior

validateOnChange value can be changed, is not just an initialization config.

Suggested Solution

validateOnChange is a function that has access to the form. Once it's been submitted it validates on change, but not before. (This is what angular does and is quite nice)

Who does this impact? Who is this for?

All users

Describe alternatives you've considered

Tried modifying the value onSubmit but there's no way to access it. Also thought of hiding the errors until submission but didn't find a way to do so.

@jaredpalmer
Copy link
Owner

Can you elaborate on this with some use cases and examples? What would the function signature of validateOnChange be?

@kompot
Copy link

kompot commented Feb 11, 2019

Use case is simple — you do not want to disturb user until after the form is submitted at least once.

So when the form is submitted at least once this value should be set to true.

So there are several possible ways to do this I guess:

  • make validateOnChange a function that has access to some kind of per field/per form isDirty flag or submitCount flat.
  • add validateBeforeFirstSubmit flag.

I was actually surprised that some of the above it's not available in Formik out-of-the-box. Seems like a basic usability feature to me.

Right now I ended up doing this

<Formik
...
render={props => (
  <form
    onSubmit={(e: React.FormEvent<HTMLFormElement>) => {
      this.setState({ formIsDirty: props.submitCount > 0 }, props.handleSubmit);
      e.preventDefault();
      return false;
    }}
...
>

@hegelstad
Copy link

hegelstad commented Apr 12, 2019

I have also been looking for a way to set validateOnChange and validateOnBlur based on some state of the form without resorting to escape hatches.

@nickjanssen
Copy link

nickjanssen commented May 11, 2019

Consider where the user has to check two boxes to agree with something (one for terms and other for privacy policy). With validateOnChange on, if the user clicks the terms checkbox, they will immediately get an error for the privacy policy checkbox, which doesn't make sense. With validateOnChange off, the errors won't disappear once they check all the boxes which also doesn't make sense. A better solution would be to add validateAfterSubmit or something.

Here's a gif for clarity's sake:
formik

My workaround is a variation of @kompot's suggestion (I'm using React Native)

      <Formik validateOnChange={state.formIsDirty}>
        <Button
          onPress={() => {
            this.setState({ formIsDirty: true }, handleSubmit);
          }}
        >
          Submit
        </Button>
      </Formik>

@stale stale bot added the stale label Jul 10, 2019
@thoughtpalette
Copy link

Still looking for a way to achieve this easily. Attempted to use useState with no luck

const [ shouldValidateOnChange, setShouldValidateOnChange ] = useState(false)
......
validateOnChange={shouldValidateOnChange}
onSubmit={(values) => {
setShouldValidateOnChange(true)
onSubmit(values.text)
}}...

@vojtechsoban
Copy link

vojtechsoban commented Aug 14, 2020

Still looking for a way to achieve this easily. Attempted to use useState with no luck

const [ shouldValidateOnChange, setShouldValidateOnChange ] = useState(false)
......
validateOnChange={shouldValidateOnChange}
onSubmit={(values) => {
setShouldValidateOnChange(true)
onSubmit(values.text)
}}...

@thoughtpalette onSubmit is probably not invoked in case of form error, I had similar issue, see @kompot workaround that works for me too.

@stevesobol
Copy link

Also trying to figure out the best way to do this

@quasipolynomial
Copy link

quasipolynomial commented Nov 20, 2020

Using the comments above, my solution is the following:

const [enableValidation, setEnableValidation] = useState(false);
...
<Formik
    initialValues={initialValues}
    onSubmit={handleSubmit}
    enableReinitialize
    validateOnChange={enableValidation}
    validateOnBlur={enableValidation}
>
    {(formikBag: FormikProps<any>) => (
        <form
            onSubmit={(event: any) => {
                setEnableValidation(true);
                event.preventDefault();
                formikBag.handleSubmit();
            }}
        >
...

@maddhruv
Copy link
Collaborator

Closing due to long inactivity

@elodszopos
Copy link

Surprised this is not incorporated into the library. I'd say validate once on submit and then on every change is a pretty standard validation strategy. .. No? Would've been nice if validateOnChange could also be a function, but we make due!

My solution, with a wrapper, in case anyone is interested (although the previously posted solutions above are probably more light-weight):

import React, { ReactElement, useEffect, useState } from 'react';
import { useFormikContext } from 'formik';
import { FormikProps } from '@components/common/form';

export type ValidationHelperProps<Schema> = {
  children?: ((props: FormikProps<Schema>) => React.ReactNode) | React.ReactNode;
  setCanValidate: (canValidate: boolean) => void;
};

export default function ValidationHelper<Schema>({ children, setCanValidate }: ValidationHelperProps<Schema>) {
  const [submitted, setSubmitted] = useState<boolean>(false);
  const { isSubmitting } = useFormikContext<Schema>();

  useEffect(() => {
    if (!submitted && isSubmitting) {
      setSubmitted(true);
      setCanValidate(true);
    }
  }, [setCanValidate, isSubmitting, submitted]);

  return children as ReactElement<FormikProps<Schema>> | null;
}

And using the above helper like ... (we have some heavier typings, I just stripped the proprietary stuff, so it's free to share and use -- in case you're wondering about why I'd re-type something that comes straight out of the lib)

export type FormProps<Schema = FormikValues> = FormikConfig<Schema> & {
  additionalClass?: string;
};

export type FormikProps<Schema> = FormikLibProps<Schema>;

export function Form<Schema = FormikValues>({ additionalClass, children, ...props }: FormProps<Schema>) {
  const [canValidate, setCanValidate] = useState<boolean>(false);

  return (
    <Formik validateOnChange={canValidate} validateOnBlur={canValidate} enableReinitialize {...props}>
      <FormikForm className={additionalClass}>
        <ValidationHelper<Schema> setCanValidate={setCanValidate}>{children}</ValidationHelper>
      </FormikForm>
    </Formik>
  );
}

@borisfullstacker
Copy link

You can do as follows, worked for me.
Hope this helps.

const [validation , setValidation] = useState(false)

const submittion = (e) =>{
    e.preventDefault()
    setValidation(true) // changes formkit.validateOnChange state to true
    return formik.handleSubmit()
}


const formik = useFormik({
    initialValues: {
      //initialize stuff
     },
    validationSchema:schema,
    onSubmit: values => {
      //do stuff
    },
    validateOnChange:validation, // initial value is false
  });

<form onSubmit={(e)=>submittion(e)}>

@ybrodsky
Copy link

ybrodsky commented Dec 3, 2021

Two years, this is still an issue.
The current way it works does not match real case use in most of the internet forms.

#3375

@nvmnghia
Copy link

@ybrodsky Can you cite some sources, research or articles about how popular this behavior is? I want it, but I'm not really sure about the UX, or that it is widely used.

@Ankita012
Copy link

return formik.handleSubmit()

This works for me :) thanks

@helenmak
Copy link

helenmak commented Jul 5, 2023

I see that that PR with the feature was opened almost 9 months ago.
Any news on the #3500?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.