logaretm / vee-validate

✅ Painless Vue forms
https://vee-validate.logaretm.com/v4
MIT License
10.74k stars 1.26k forks source link

Validators are run when validateOnValueUpdate is set to false #4178

Open jlahtinen opened 1 year ago

jlahtinen commented 1 year ago

Is your feature request related to a problem? Please describe.

I have a custom input that renders multiple files and single input. They report errors dynamically like described in https://vee-validate.logaretm.com/v4/examples/dynamic-validation-triggers/ . It seems that on every v-model change watcher notifies that change and starts validateValidStateOnly validation https://github.com/logaretm/vee-validate/blob/044b4b44601908330c65541ce2bee6a110b1604f/packages/vee-validate/src/useField.ts#L245 when validateOnValueUpdate is set to false.

This means that our custom validator is called on every time v-model changes and errors are not populated even though validator returns errors. This is quite ok. Problem is that if validation is heavy and would be better if validated only when form.validate() is called.

Describe the solution you'd like

So I would like that

  1. it would be possible to know in a validator that is validation started by form.validate
  2. it would be possible to know in a validator that are errors populated or not
  3. validator is not called at all if errors are not populated
logaretm commented 1 year ago

As you noted, this is intended because we need to ensure meta.valid is correct regardless of whether errors exist. Otherwise, I will be getting a lot of issues from people asking "why a valid flag is not accurate?" which has already happened a few times in v3.

it would be possible to know in a validator that is validation started by form.validate

This may work in custom validators (functions) but can't be used with yup or zod.

it would be possible to know in a validator that are errors populated or not

This might be a good suggestion, but would also only benefit the custom validators (functions) and none of the other styles of validation will be able to utilize it.


How expensive your validator function is really? What does it do? If its an API call you could debounce it to make sure it doesn't run too many times for the same field/form.

I will keep this marked as an enhancement as I try to explore some kind of compromise here.

jlahtinen commented 1 year ago

Yes our expensive ones are API calls. We can currently keep value as null and do not fire API call until value is not null. This way we can know should errors be populated or not. But this "keeping value as null" is not too intuitive and makes code base a little more complicated. There is now also one more place to add logic about when to show errors and when not.

brandonburkett commented 1 year ago

I spent a few hours on this today trying to figure out why async validators were running with useField validateOnValueUpdate: false and using handleBlur and handleChange events (omitting @input event).

Then I noticed I had v-model="value" on the custom input, which makes sense that value would be updated. I just assumed validateOnValueUpdate would opt out of the rules being run until I explicitly called handleBlur / handleChange with shouldValidate true / false.

Removing v-model="value" in favor of :value="value" and manually invoking handleChange seemed to solve it for me.

gretchelin commented 10 months ago

Hi, is there any update on this issue?

Currently trying to make a form to only validate onSubmit but passing validateOnValueUpdate into useField doesn't have any effect. I have a similar setup to the example here: https://vee-validate.logaretm.com/v4/examples/custom-inputs/

By the way, validateOnValueUpdate doesn't work either on that example (I've tried adding it to the TextInput component on line 46, but the validation still run anyways. Is this prop no longer available? I've tried searching in useField guide here: https://vee-validate.logaretm.com/v4/api/use-field/ but there is no definition on validateOnValueUpdate, just a passing mention to set it to true/false depending on the context.