Interaction and UX
Client-side validation is a UX tool for your users, as such there are many strategies regarding when to validate?.
There are multiple common strategies:
- Aggressive: Triggered when the user presses a key (on
input
). - Passive: Triggered when the form is submitted.
- Lazy: Triggered when the user leaves the input (on
blur
orchange
). - Eager: Is a combination of
aggressive
andlazy
, as it first validates when the user leaves the input (onblur
orchange
) then if the input is invalid it will behave aggressively until the input is valid again and it will go back to being lazy.
Interaction Modes
vee-validate implements those common strategies for you, which are called "interaction modes".
Setting The Interaction Mode Globally
You can set the interaction mode for all of the ValidationProvider
instances by using the exported setInteractionMode
function.
import { setInteractionMode } from 'vee-validate';
setInteractionMode('lazy');
Setting The Interaction Mode Per Component
You can alternatively set it per ValidationProvider
by passing a mode
prop.
<ValidationProvider mode="lazy" rules="required" v-slot="{ errors }">
<!-- Some input -->
</ValidationProvider>
Here are some examples for the default modes available:
Aggressive (Default)
This is the default mode for vee-validate. Validates on input
and blur
.
Lazy
Validates on change
or blur
.
Passive
Does not validate unless validate
is called explicitly.
Eager
This is arguably a better UX for your users since it isn't aggressive initially. It is eager to pass which is reason of its name.
Behaves like lazy when the field wasn't interacted with yet, and if it is invalid it will be aggressive until the input becomes valid again.
Custom Modes
You can define new custom modes, interaction modes are a simple function that takes a context object with the following structure:
interface ModeContext {
errors: string[];
value: any;
flags: ValidationFlags;
}
For example the eager rule implementation looks like this:
const eager = ({ errors }) => {
if (errors.length) {
return {
on: ['input', 'change']
};
}
return {
on: ['change', 'blur']
};
};
You can pass the function directly to the mode
prop on the ValidationProvider
:
<ValidationProvider :mode="custom" rules="required" v-slot="{ errors }">
<input v-model="value" type="text" placeholder="type something">
<span>{{ errors[0] }}</span>
</ValidationProvider>
<script>
export default {
data: () => ({
value: ''
}),
methods: {
custom(context) {
if (context.value === 'yes') {
return {
on: ['input']
};
}
return { on: ['change'] };
}
}
};
</script>
Or you can set it globally with setInteractionMode
:
import { setInteractionMode } from 'vee-validate';
setInteractionMode('custom', context => {
if (context.value === 'yes') {
return {
on: ['input']
};
}
return { on: ['change'] };
});
Note
The mode
prop takes precedence over the globally configured mode, using setInteraction
in runtime will only affect the new Providers created after its call.