Vee-validate: Validate on Blur, but validate correctly on input

Created on 25 Jun 2018  Â·  18Comments  Â·  Source: logaretm/vee-validate

Is your feature request related to a problem? Please describe.
Whenever using validate on blur, the user does not get feedback when re-entering the field, only after blurring.

Describe the solution you'd like
A good solution would be to always validate the input field, but only changing the state of the field when the field has been entered correctly to provide instant feedback when they correct their mistake.

An example flow would be for an input field with blur validation without the proposed:

  1. User enters input field with email incorrectly and blurs
  2. Validation fails
  3. User corrects mistake, but doesn't see their warning message dissapear.
  4. User blurs
  5. Validation succeeds

The preferred method would be:

  1. User enters input field with email incorrectly and blurs
  2. Validation fails
  3. User corrects mistake, and instantly sees when user has correctly fixed their mistake
duplicate request ✨ enhancement 🛳 In PR

Most helpful comment

@Dylan-Chapman Well that makes the API messier than I would like. I'm thinking about a new behavior feature, where you can define multiple strategies for validation behavior with listeners, for example:

const behaviors = ['eager', 'aggressive', 'none'];

Vue.use(VeeValidate, {
  behavior: 'eager' // if the field has an error and the user just entered a valid value, remove the error
});

I would call the requested behavior eager as in its eager for success status, while the default being aggressive. This is undoubtedly more complex than your suggestion and would require a small state machine implementation so users can make their own behaviors, but I like how the API is being defined in this case.

But there are issues with the concept itself, remote rules will always be executed in the background since the listeners will only control when to show the error rather than when to validate which is the current behavior.

All 18 comments

Just a thought in terms of creating an API for this... when declaring your input events, you could do something like events: blur.input which would mean: validate on blur if the validated flag is false, and validate on input if the validated flag is true.

@Dylan-Chapman Well that makes the API messier than I would like. I'm thinking about a new behavior feature, where you can define multiple strategies for validation behavior with listeners, for example:

const behaviors = ['eager', 'aggressive', 'none'];

Vue.use(VeeValidate, {
  behavior: 'eager' // if the field has an error and the user just entered a valid value, remove the error
});

I would call the requested behavior eager as in its eager for success status, while the default being aggressive. This is undoubtedly more complex than your suggestion and would require a small state machine implementation so users can make their own behaviors, but I like how the API is being defined in this case.

But there are issues with the concept itself, remote rules will always be executed in the background since the listeners will only control when to show the error rather than when to validate which is the current behavior.

That would be really great feature for user experience :)

@logaretm

Perhaps a solution would consist of something like this:

Vue.use(VeeValidate, {
            statusEvents: {
                'pristine': 'blur',
                'invalid': 'change',
                'valid': 'blur'
            }
        });

statusEvents (or something similar) indicates the behavior per state of a field, where you could add listeners, and change the validation method for the field.

Provides a lot of configuration for the user. This feature would be a great improvement for usability!

P.S. It's a great plugin as it is, by far the best form validation tool i've used, so thank you!

I like the approach @CephNightmare mentioned. It's simple/intuitive and you can maintain backwards compatibility by just allowing events to optionally take a flag-keyed object, while falling back to an all-flags-based validation (when using a string value) like it does currently.

Just started using this plugin and this would be great to have! I really don't want to write any custom validation to perform this if it can be part of the API itself.

The following something work.
javascript= Vue.use(VeeValidate, { events: 'input|change|blur', });

Did you add this feature? @logaretm

@tz136 Still working on getting few things correctly before I get to this one, I have a working draft for the ValidationProvider component, but the directive would be very tricky to implement for (might require a re-write I have been planning for some time).

Any update on this issue?

@logaretm any news or eta ? :)

Also eagerly looking forward to this.

@aldarund So far the proposed API is to allow a function to provide an object of options for each field after each validation/render cycle. I would call a function that does this a "strategy" similar to what passport is doing.

Anyways a validation strategy is able to provide a list of events that the next validation attempt should trigger on, along with a "debounce".

I only implemented it so far for the ValidationProvider component

<template>
  <ValidationProvider :strategy="myStrat">
  // ...
  </ValidationProvider>
</template>

<script>
export default {
  methods: {
    // strats will receive an object containing
    // useful contextual information about the field.
    // like the current errors, if its valid or not.
    // also the list of flags.
    myStrat ({ errors, valid, untouched }) {
      if (valid) {
       // must always return an object.
        return {
         events: ['blur']
        }; 
      }

      // must always return an object.
      return {
       events: ['input']
      };
    }
  }
};
</script>

This last example shows a strategy that validates on blur when the field is valid. But once the field becomes invalid It will validate on each input event until the field becomes valid again, so its "eager" for success, you could register it globally as well.

import { strategy } from 'vee-validate';

strategy('eager', ({ errors, valid, untouched }) => {
  if (valid) {
    return {
      events: ['blur']
    }; 

  // must always return an object.
  return {
   events: ['input']
  };
});

There are still issues to iron out like cross-field validation rules like confirmed and impure rules where the value doesn't necessarily correspond to a valid state or not at any point in time, think of uniq or Math.rand() > 0.5, also the events option will be useless after this feature as its just a static "strategy". I have to decide few policies on that to properly document them.

For the directive, it would probably follow a global config option. Still, The directive needs to be re-written to take advantage of re-renders. Otherwise, it would be hard to implement for it in the current codebase (lots of moving parts).

@logaretm have you seen the simple-vue-validator Interaction Modes? http://simple-vue-validator.magictek.cn/#m_modes. Unfortunately it does not have a mode that works as desired here (see https://github.com/semisleep/simple-vue-validator/issues/53) but it has at least formalized the idea of interaction modes plus implemented and documented some options.

Anyways a validation strategy is able to provide a list of events that the next validation attempt should trigger on, along with a "debounce".

I only implemented it so far for the ValidationProvider component

This is exactly what I need in ValidationProvider. (Hoping for a release in a near future.)

@tsongas I like the __interaction mode__ concept as a replacement to the events configuration. This will be breaking change for all users but for the simplicity sake, I prefer users to be able to customize the events via one source only. So I will release a couple of intermediary releases deprecating the events option.

@savehansson I think I'm able to do a release in a few days with this feature implemented in ValidationProviders, It works fine so far in my tests. We just have to test it with my team to see if the whole thing "feels right".

When can we expect this to be released on npm?

@ZacJoffe It's live since a couple of weeks:
Doc: https://baianat.github.io/vee-validate/guide/interaction.html

Was this page helpful?
0 / 5 - 0 ratings

Related issues

yyyuuu777 picture yyyuuu777  Â·  3Comments

YamenSharaf picture YamenSharaf  Â·  3Comments

DanielPe05 picture DanielPe05  Â·  3Comments

parweb picture parweb  Â·  3Comments

Hoagiex picture Hoagiex  Â·  3Comments