-
Notifications
You must be signed in to change notification settings - Fork 2
How to use
vue-convenia-validator is a model-based, template-independent validation library, which means that it is completely decoupled from how you build your templates.
Instead, it takes the input values of your form directly from the data
of your
component and validates it according to the validation rules you defined for
each field in your component.
This little guide will provide in-depth explanation of all the ways you
can use the validator you've been warned.
In order to use the validator, first you'll need to import the FormValidator
mixin and use it on the component you wish to have form validation:
<template>
<div id="vue-app">
<form>
<input name="fullName" type="text" v-model="fullName" />
<input name="birthday" type="text" v-model="birthday" />
</form>
</div>
<template>
<script>
import FormValidator from 'vue-convenia-validator'
export default {
mixins: [ FormValidator ],
data () {
return {
fullName: '',
birthday: ''
}
}
}
<script>
There are two ways you can initialize the validator in your component:
-
You can defined a
validations
object in the root level of your component, we'll go into the structure of this object in a bit. -
You can simply use
$this.validator.init(<ValidationsObj>)
whenever you want anywhere in your app
For those that are familiar with TypeScript, the object containing your form(s) field validations that you have to pass to the validator is defined as follows:
export type FieldValidation = string | Array<string> | { [rule: string]: any }
export type FormValidation = { [fieldName: string]: FieldValidation }
export type ScopedFormValidation = { [scope: string]: FormValidation }
export type FormTemplate = ScopedFormValidation | FormValidation
Ultimately, the object that the validator receives from your componente has
to follow the FormTemplate
signature. Now, for those that aren't
familiar with TypeScript, what this means is (bear with me):
First of all, the structure of this object basically matches the structure of the data in your component, where you have the actual values for each field in your form. So in practice, this means that if I have my data structured in this manner:
data () => ({
fieldOne: '',
fieldTwo: 'potato'
})
The validation object would look like this:
validations: {
fieldOne: 'required',
fieldTwo: 'alphanumeric'
}
But if it looks like this:
data () => ({
formOne: {
fieldOne: '',
fieldTwo: 'potato'
}
})
My validation object must look like this:
validations: {
formOne: {
fieldOne: 'required',
fieldTwo: 'alphanumeric'
}
}
By the way, this thing we used in the last example is called a scope
,
scopes allow us to use the validator with multiple formularies on the
same componente, avoiding conflict with field names and form validation
states etc. Basically I can have formOne.fieldOne
and formTwo.fieldOne
,
on the same componente and these two formularies will be validated
separately (you can't have two scopes with the same name of course).
That's basically what the type signature of FormTemplate
means, you can
either have an object with scopes (e.g. { formOne: { field: '', ... }, formTwo: { field: '' , ... }, ... }
), or an object with the rules of
each field directly, but it has to match the structure of the data
in your component.
In the previous section I've shown four TypeScript types, the section also explains what the last two means, now onto the first two:
export type FieldValidation = string | Array<string> | { [rule: string]: any }
export type FormValidation = { [fieldName: string]: FieldValidation }
Basically what this means is that, the rule that you'll defined for each field can either be a string, an array of strings, or an object (it's not very clear in the type, but it can also be a function that returns one of these three):
validations: {
fieldOne: 'required',
fieldTwo: ['required', 'dateFormat'],
fieldThree: { regex: '/\D{5}/', },
fieldFour: (formData) => ({ custom: () => formData.fieldOne === 'bla' })
}
Now let's go through each of these four possibilities and what they mean:
-
String: When the value of the validation is simply a string, you're just passing the name of the rule you want to apply to this field.
-
Array: An array of string is basically an array of rules you want to apply to a certain field, you use this form when you just wanna use more than one rule on a given field.
-
Object<{ [ruleName]: any }>: Now, when you pass an object as the validation for a field, it acts similarly to an array, you can use more than one rule for a given field, but not only that: some rules also accept arguments, normally you can pass arguments to a rule even in string format (e.g.
fieldName: '<ruleName>:<arguments>'
, that would look like:dateFormat:YYYY-MM-DD
) but when you pass an object you can use even more complex arguments. Some rules even accept functions as arguments, but we'll go into these more advanced uses later on. -
Function <(formData, validations) => FieldValidation>: You use functions for your field validations when you need more complex logic. This function must return one of these three last options, it will basically return the actual validation rule, either an string, array of strings of object. The difference here is that the function allows you to have access to the state of the form and the validation state of each field (we'll go into that later), so you can dinamically change the validation rules of a field according to the state of the form, among other things.
That's basically it for field rules, we'll go into much more detail about all the cool stuff you can do with them in a dedicated page about each rule and types of rules.
It's important to note that each input
field in your template must have a
name
property that corresponds to the variable name in the data
. For example:
<template>
<form>
<input name="fieldOne" type="text">
</form>
</template>
<script>
export default {
data: () => ({
fieldOne: ''
})
}
</script>
And for each scope
you have, each form in your template must also have
a corresponding name
property:
<template>
<div>
<form name="formOne">
<input name="fieldOne" type="text">
</form>
<form name="formTwo">
<input name="fieldOne" type="text">
</form>
</div>
</template>
<script>
export default {
data: () => ({
formOne: { fieldOne: '' },
formTwo: { fieldOne: '' },
})
}
</script>
Once you declare the validation rules for each of your fields, the validator
will initialize these rules, look for the correspoding elements in the DOM,
and trigger each the field validation whenever it changes.
At this point, the validation of your forms should be working, and you'll have
a $validations
computed object accessible from the componente where you
registered the FormValidator
mixin, this computed object contains the
validation state for each field of each form you have registered for validation.
Assuming we have registered our field validations in our component like this:
export default {
data: () => ({
formOne: {
fieldOne: '',
fieldTwo: '',
},
formTwo: {
fieldOne: "I'm filthy",
fieldTwo: ''
}
}),
validations: {
formOne: {
fieldOne: 'required',
fieldTwo: 'dateFormat'
},
formTwo: {
fieldOne: 'numeric',
fieldTwo: 'pis'
}
},
methods: {
...
}
}
Our $validations
computed object will look like this:
{
formOne: {
fieldOne: {
pristine: true,
dirty: false,
changed: false,
touched: false,
valid: false,
errors: []
},
fieldTwo: {
pristine: true,
dirty: false,
changed: false,
touched: false,
valid: false,
errors: []
}
},
formTwo: {
fieldOne: {
pristine: false,
dirty: true,
changed: false,
touched: false,
valid: false,
errors: []
},
fieldTwo: {
pristine: true,
dirty: false,
changed: false,
touched: false,
valid: false,
errors: []
}
}
}
For each field of each form, the validator
will generate this flags and update
them whenever the field's value changes. Heres what each of these flags mean:
{ pristine: 'True if the value of the field is empty, false otherwise.'
, dirty: 'True if the value of the field is not empty, false otherwise.'
, changed: 'True if the current value of the field is different from its initial value, false otherwise.'
, touched: 'Becomes True once the `blur` event triggers for the respective field element.'
, valid: 'True if all the validation rules applied to this field pass without errors, false otherwise.'
, errors: 'An array of error messages, each validation rule registered to this field that fails the, will add it"s default error message to this array.'
}
I think that's it for the basics (i know its a lot sorry), for even more in-depth information about the API, checkout our API Reference, for more information about each rule and how they work, see the Rules Reference.