form-validation-manager v2.3.0
beta version of fvm for vue3 (composition api) and vue2
Some bugs may still present, please report them
Form Validation Manager - fvm
v2.x.x is compatible with vue2, vue3(options api) and vue3(composition api) v1.x.x is only compatible with vue2
Simple, lightweight model-based validation for Vue.js
Inpired by vuelidate
This plugin usage is similar of vuelidate
Why a new plugin ?
Instead of vuelidate this one allow fine error report and custom messages\ and a better integreation in templates
- Model based
- Decoupled from templates
- Minimalistic library
- Support for collection validations
- Support for nested models
- Contextified validators
- Easy to use with custom validators (e.g. Moment.js)
- Easy errors messages customisation
Summary
Installation
npm install form-validation-manager --save
Vue 2 :
Import the library and use as a Vue plugin to enable the functionality globally on all components containing > > validation configuration.
import Vue from 'vue' import Fvm from 'form-validation-manager/vue2' //for typescript import * as fvmTypes from 'form-validation-manager/vue2/types'; import * as fvmTypesValidators from 'form-validation-manager/validators/types'; Vue.use(Fvm)
Basic usage
Vue2 options-api
import { and, required, numeric, gte, length } from 'form-validation-manager/validators'
export default {
data () {
return {
form:{
name: '',
age: 0
}
}
},
validations: {
form:{
name: and(required(), length(gte(3))),
age: and(required(), numeric(), gte(21))
}
},
methods:{
submit(){
if(this.$fvm.$isValid){
//do something
}
}
}
}
a validation oject is generated with the same tree as 'validations'
//generated object
//$fvm
{
$errors:String[],
$error:Boolean,
$isValid:Boolean,
$invalid:Boolean,
$dirty:Boolean,
$pristine:Boolean,
$pending:Boolean,
validate: ()=>void
form:{
$errors:String[],
$error:Boolean,
$isValid:Boolean,
$invalid:Boolean,
$dirty:Boolean,
$pristine:Boolean,
$pending:Boolean,
validate: ()=>void
name:{
$errors:String[],
$error:Boolean,
[...]
},
age:{
$errors:String[],
$error:Boolean,
[...]
}
}
}
- $errors :
- string[]
- For each 'non-final' node : $errors Array concatenate $errors of sub nodes
- $error : node (or sub nodes) has one or more errors
- $isvalid : node (or sub nodes) as no errors
- $invalid : node (or sub nodes) has one or more errors
- $dirty : node (or sub nodes) have been edited by user
- $pristine : node (or sub nodes) have not been edited by user
- $pending : node (or sub nodes) wait for an async validation result
- _validate : force validation of node (and sub nodes)
Vue3 options-api
import { and, required, numeric, gte, length } from 'form-validation-manager/validators'
import { useFvm } from 'form-validation-manager/vue3'
export default {
data () {
return {
form:{
name: '',
age: 0
}
}
},
validations: {
form:{
name: and(required(), length(gte(3))),
age: and(required(), numeric(), gte(21))
}
},
setup:()=>({ fvm$: useFvm()})
}
or
import { and, required, numeric, gte, length } from 'form-validation-manager/validators'
import { useFvm } from 'form-validation-manager/vue3'
export default {
data () {
return {
form:{
name: '',
age: 0
}
}
},
setup(){
return{
fvm$ : useFvm({
form:{
name: and(required(), length(gte(3))),
age: and(required(), numeric(), gte(21))
}
})
}
}
}
validation state is accessible with fvm$
or this.fvm$
Vue3 Composition API
import { and, required, numeric, gte, length} from 'form-validation-manager/validators'
import { useFvm } from 'form-validation-manager/vue3'
export default {
setup () {
const form = reactive({
name: '',
age: 0
});
const validation = useFvm(form, {
name: and(required(), length(gte(3))),
age: and(required(), numeric(), gte(21))
});
return { validation, form };
}
}
validation state is accessible with validation
Specials nodes
export default {
data () {
return {
form:{
list:[
{id:1, value:15}
{id:2, value:0}
],
parent:{
child: {
property:'value'
}
}
}
}
},
validations: {
form:{
liste:{
$each:{
value:gt(0)
}
},
parent:{
$self: custom(function()=>{ /* ...*/ }), //validate parent obj
child:{
property: regexp(/.../) //validate child's property
}
}
}
}
}
- $each : loop over elements of an array
- $self : allow to validate parent and child nodes
Validators
values validation
// generic validators
required()
eq(value) // equal
// number validators
numeric() // is numeric
gt(min) // greater than >
gte(min) // greather than equal >=
lt(max) // less than <
lte(max) // less than equal <=
between(min,max[,exclude])
// string validators
isString()
regexp(expr:RegExp)
includes(str:String)
isDate(format:String='yyyy-MM-dd') // value must be a string date
email() //is email address
logic
and(...validators) // all validators must be ok
andSequence(...validators) // all validators must be ok, call next validator only if previous one is OK
or(...validators) // minimum one validtor must be ok
xor(...validators) // only one validator must be ok
_if(condition:(value,context)=>Boolean, thenValidator[, elseValidator])// apply thenValidator only if condition function returned value is true else apply elsevalidator if defined
not(validator) // validator must be KO
optional(validator) //execute validator only if value != null, undefined or ""
specials
pick(property, validator) // validate value[property] instead of value itself
length(validator) // pick length
withMessage(validator,message) // customise validator message
empty() // always ok validator
custom((value, context)=>Boolean|String|String[]) // allow user to create custom validators
async((value, context)=>Promise<Boolean|String|String[]>, forceRenderUpdateAuto=true, debounceTime=0) // allow user to create custom async validators
revalidate(...paths) // force properties revalidation if this one change
// exmple with previous code : revalidate('form.name')
Arrays
A special node '$each' allow to validate each elements of an array
export default {
data () {
return {
form:{
list : [-1, 5, 10]
}
}
},
validations: {
form:{
list:{
$each : {
and(
gt(0),
custom(function(value,context){
// custom validation code
})
)
}
}
}
}
}
Note : using custom validator under
$each
:context.indexes
contain $each loops indexes. Here :{ 0:<possible values : 0,1,2>, list:<possible values : 0,1,2>, length:1 }
for more details about custom validator, see Custom validation
Messages
withMessage wrapper allow to customise error message
export default {
data () {
return {
form:{
age: 0
}
}
},
validations: {
form:{
age: and(
withMessage(
and(required(), numeric()),
'field is required and must be a number'
),
withMessage(
gte(21),
'you must be of age'
)
)
}
}
}
the property '$errors' will contain defined errors messages if field isnt valid.
Custom validation
component method
a custom method can be used as validator.\ inside this one, 'this' refer to current component
export default {
data () {
return {
form:{
age: 0
}
}
},
validations: {
form:{
age: custom(function(value, context){ //do not use arrow function if you want to use 'this'
return this.myValidationMethod(value, context);
})
}
},
methods:{
myValidationMethod(value, context){
// ...
}
}
}
myValidationMethod must return false if no error and true|string|string[] if one or more errors occured
context
contain properties:
component
: current component
path
: current property path (form.age
here)
optional indexes
: contain $each
loops indexes, see $each section
Reusable validator
You may want to define a validator and use it in different components\ best way is to define it in separate .js file
import { Validator } from 'form-validation-manager/validators';
export default function myValidator(arg1, arg2) {
return new Validator('myValidator', (value:any, context:Context) => {
if( /* test rule 1 KO */){
return 'message 1'
}
if( /* test rule 2 KO */){
return 'message 2'
}
// is valid
return false
});
}
and use it
import myValidator from './my-validator'
export default {
data () {
return {
form:{
age: 0
}
}
},
validations: {
form:{
age: myValidator('val1', 'val2')
}
}
}
Async validation
export default {
data () {
return {
form:{
age: 0
}
}
},
validations: {
form:{
age: async(function(value, context){
return new Promise(resolve=>{
// async stuf
resolve(myValidationResult)
})
}, debounceTime)
}
},
}
- debounceTime: number : in ms, optional, default=0, if > 0 debounce calls
Before submiting form, you must wait for $pending == false.\ Exemples :
- In template :
<form>
<!-- -->
<button type="submit" :disabled="$form.$pending || $form.$error" @click="submit()">Send</button>
</form>
Integration with vuetify
export default {
data () {
return {
form:{
age: 0
}
}
},
validations: {
form:{
age: and(
withMessage(
and(required(), numeric()),
'age is required and must be a number'
),
withMessage(
gte(21),
'you must be of age'
)
)
}
}
}
<v-text-field
:rules="$fvm.form.age.$errors"
/>
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago