Some background:
I have a form where I validate on change, and use the isValid prop to control whether the submit button is enabled or disabled.
The problem for me is that isValid is computed based on the dirty values, and a field isn't considered touched/dirty until a blur happens. I want the submit button to be enabled as soon as the form is in valid state, even while typing. Right now this doesn't happen until an input loses focus.
This feels weird to me. validateOnChange gives me the impression that it in some way should have a say over the isValid prop.
This would be fixed by marking a value as touched when an onChange happens, which makes sense to me at least. While typing, I am definitely "touching" it.
I could provide a pull request for this if you are interested.
And finally, thank you so much for this great library!
Pass validateOnChange: true and validateOnBlur: false to your form鈥檚 options
@jaredpalmer this doesn't help in my case.
I forked the codesandbox example to illustrate this: https://codesandbox.io/s/xGw0KRZ6E
As you can see, the submit button is disabled while the form is invalid (the isValid prop).
The submit button won't be enabled until I blur the field, even though you've typed in a valid email address. After the first blur, it works as expected, because the field is then touched.
Would you be willing to reopen this issue?
We've hit this problem too.
A form becomes dirty if a field has been touched, not if a field has been changed.
https://github.com/jaredpalmer/formik/blob/b38806ccd79d49dcf6bd41c29d81d73b4508f068/src/formik.tsx#L530-L531
If a field is dirty, isValid uses the data in values. If it's not dirty it uses isInitialValid.
https://github.com/jaredpalmer/formik/blob/b38806ccd79d49dcf6bd41c29d81d73b4508f068/src/formik.tsx#L538-L543
In forms with a single field and validateOnChange, the field gets changed before there's been a blur event, so the form isn't yet dirty and formik doesn't look at the value when calculating isValid
We hacked around this with
handleChange={(...args) => {
handleChange(...args);
handleBlur(...args);
}}
Should the definition of dirty be changed? I'd expect a form to be dirty once the first change is made
@skattyadz feel free to submit a PR on this
I think this (and some other edge cases) can be fixed with adding touchOnChange and touchOnBlur options
We don't want a change event to mark the field as touched because then you would have validation errors appear while in the process of typing initial input into an empty field, which is bad UX.
We could separate the concept of touched and dirty and have the latter get set onChange and not the former, but that feels confusing.
I think instead we should store the result of the most recent validation in form state, and isValid() can just check that. If there has not been a validation yet, it can use isInitialValid.
I ran into this issue, and I solved it by passing the setFieldTouched function to the onInput event handler. For example,
<input
...
onInput={() => setFieldTouched(/* nameOfField */, true, true)}
...
/>
^ will set the status of that input to touched as soon as the user enters something.
Also, checkout the list of events in the react docs: https://reactjs.org/docs/events.html#touch-events.
Seems that these 2 added options were finally removed? In my opinion, they are very useful. Can you reopen this issue? @jaredpalmer
We don't want a change event to mark the field as
touchedbecause then you would have validation errors appear while in the process of typing initial input into an empty field, which is bad UX.
Well, IMO lots of people like this kind of UX, and dislike that a field is not validated until blurred. Can we have this as an option?
I second what @chenjianjx mentioned which provides a realtime feedback experience.
Another thing is I noticed dirty will get set to true upon focus, which is actually what I imagine touched to behave at first. Now I realize formik only sets touched after onBlur, where you need to go through focus -> unfocus in order to trigger this; the first time you "touched" / focus the input actually does not set touched to true.
Looks like currently dirty only reflects on a form-level. Would be great if dirty can be set up at field-level.
Most helpful comment
Well, IMO lots of people like this kind of UX, and dislike that a field is not validated until blurred. Can we have this as an option?