Validator component for Vue.js
- Vue.js
1.0.10
+
vue-validator is still alpha verison. Maybe, There are some breaking change. If you have some feedback, we are welcome in Vue.js Discussion 😺
$ npm install vue-validator
git clone https://github.com/vuejs/vue-validator.git node_modules/vue-validator
cd node_modules/vue-validator
npm install
npm run build
When used in CommonJS, you must explicitly install the router via Vue.use()
:
var Vue = require('vue')
var VueValidator = require('vue-validator')
Vue.use(VueValidator)
You don't need to do this when using the standalone build because it installs itself automatically.
jsdelivr
<script src="https://cdn.jsdelivr.net/vue.validator/2.0.0-alpha.9/vue-validator.min.js"></script>
new Vue({
el: '#app'
})
We can use validator
element directive and v-validate
directive. The following is an example:
<div id="app">
<validator name="validation1">
<form novalidate>
username: <input type="text" v-validate:username="['required']"><br />
comment: <input type="text" v-validate:comment="{ maxlength: 256 }"><br />
<div>
<span v-show="$validation1.username.required">Required your name.</span>
<span v-show="$validation1.comment.maxlength">Your comment is too long.</span>
</div>
<input type="submit" value="send" v-if="$validation1.valid">
</form>
</validator>
</div>
The validation results keep to validation scope as defined with vue-validator. In above case, the validation results keep to $validation1
scope (prefixed with $
) which was specified with name
attribute of validator
element directive.
The structure of validation results that was kept to validation scope is the below:
$validation.valid
.invalid
.touched
.untouched
.dirty
.pristine
.modified
.messages.field1.validator1
...
.validatorX
.field2.validator1
...
.validatorX
.field1.validator1
...
.validatorX
.valid
.invalid
.touched
.untouched
.dirty
.pristine
.modified
.messages.validator1
...
.validatorX
...
.fieldX.validator1
...
.validatorX
.valid
.invalid
.touched
.untouched
.dirty
.pristine
.modified
.messages.validator1
...
.validatorX
The various top-level properties has been defined in the validation scope, and the each field validation result has been defined as field namespace.
valid
: whether field is valid. if it's valid, then returntrue
, else returnfalse
.invalid
: reverse ofvalid
.touched
: whether field is touched. if field was focused, returntrue
, else returnfalse
.untouched
: reverse oftouched
.modified
: whether field value is modified. if field value was changed from initial value, returntrue
, else returnfalse
.dirty
: whether field value was changed at least once. if so, returntrue
, else returnfalse
.pristine
: reverse ofdirty
.messages
: if invalid field exist, return error message wrapped with object, elseundefined
.
valid
: whether all fields is valid. if so, then returntrue
, else returnfalse
.invalid
: if invalid field exist even one in validate fields, returntrue
, elsefalse
.touched
: whether all fields is touched, if so, returntrue
, elsefalse
.untouched
: if untouched field exist even one in validate fields, returntrue
, elsefalse
.modified
: if modified field exist even one in validate fields, returntrue
, elsefalse
.dirty
: if dirty field exist even one in validate fields, returntrue
, elsefalse
.pristine
: whether all fields is pristine, if so, returntrue
, elsefalse
.messages
: if invalid even one exist, return all field error message wrapped with object, elseundefined
.
v-validate
directive syntax the below:
v-validate:field="array literal | object literal | binding"
The vue-validator version 2.0-alpha or earlier, validation result had been kept per v-model
. In 2.0-alpha later, use the argument of v-validate
directive instead of v-model
.
~v1.4.4:
<form novalidate>
<input type="text" v-model="comment" v-validate="minLength: 16, maxLength: 128">
<div>
<span v-show="validation.comment.minLength">Your comment is too short.</span>
<span v-show="validation.comment.maxLength">Your comment is too long.</span>
</div>
<input type="submit" value="send" v-if="valid">
</form>
v2.0-alpha later:
<validator name="validation">
<form novalidate>
<input type="text" v-validate:comment="{ minlength: 16, maxlength: 128 }">
<div>
<span v-show="$validation.comment.minlength">Your comment is too short.</span>
<span v-show="$validation.comment.maxlength">Your comment is too long.</span>
</div>
<input type="submit" value="send" v-if="valid">
</form>
</validator>
As well as Vue.js, you can use the kebab-case at the argument of v-validate
.
below the example:
<validator name="validation">
<form novalidate>
<input type="text" v-validate:user-name="{ minlength: 16 }">
<div>
<span v-if="$validation.userName.minlength">Your user name is too short.</span>
</div>
</form>
</validator>
The below is example that using array literal:
<validator name="validation">
<form novalidate>
Zip: <input type="text" v-validate:zip="['required']"><br />
<div>
<span v-if="$validation.zip.required">Required zip code.</span>
</div>
</form>
</validator>
Like the required
, if you don't need to specify the rule, you should use it.
The below is example that using object literal:
<validator name="validation">
<form novalidate>
ID: <input type="text" v-validate:id="{ required: true, minlength: 3, maxlength: 16 }"><br />
<div>
<span v-if="$validation.id.required">Required Your ID.</span>
<span v-if="$validation.id.minlength">Your ID is too short.</span>
<span v-if="$validation.id.maxlength">Your ID is too long.</span>
</div>
</form>
</validator>
You can specify the rule value on the object literal. Like the required
, you can specify the dummy rule value on the literal object.
And also, you can specify strict object as the below:
<validator name="validation">
<form novalidate>
ID: <input type="text" v-validate:id="{ minlength: { rule: 3 }, maxlength: { rule: 16 } }"><br />
<div>
<span v-if="$validation.id.minlength">Your ID is too short.</span>
<span v-if="$validation.id.maxlength">Your ID is too long.</span>
</div>
</form>
The below is example that using binding:
new Vue({
el: '#app',
data: {
rules: {
minlength: 3,
maxlength: 16
}
}
})
<div id="app">
<validator name="validation">
<form novalidate>
ID: <input type="text" v-validate:id="rules"><br />
<div>
<span v-if="$validation.id.minlength">Your ID is too short.</span>
<span v-if="$validation.id.maxlength">Your ID is too long.</span>
</div>
</form>
</validator>
</div>
In addition to the above data scope example, you can specify also the computed property or methods.
You can validate checkbox. the below example:
<div id="app">
<validator name="validation1">
<form novalidate>
<h1>Survey</h1>
<fieldset>
<legend>Which do you like fruit ?</legend>
<input id="apple" type="checkbox" value="apple" v-validate:fruits="{
required: { rule: true, message: requiredErrorMsg },
minlength: { rule: 1, message: minlengthErrorMsg },
maxlength: { rule: 2, message: maxlengthErrorMsg }
}">
<label for="apple">Apple</label>
<input id="orange" type="checkbox" value="orange" v-validate:fruits>
<label for="orange">Orage</label>
<input id="grape" type="checkbox" value="grage" v-validate:fruits>
<label for="grape">Grape</label>
<input id="banana" type="checkbox" value="banana" v-validate:fruits>
<label for="banana">Banana</label>
<ul class="errors">
<li v-for="msg in $validation1.fruits.messages">
<p>{{msg}}</p>
</li>
</ul>
</fieldset>
</form>
</validator>
</div>
new Vue({
el: '#app',
computed: {
requiredErrorMsg: function () {
return 'Required fruit !!'
},
minlengthErrorMsg: function () {
return 'Please chose at least 1 fruit !!'
},
maxlengthErrorMsg: function () {
return 'Please chose at most 2 fruits !!'
}
}
})
You can validate radio button. the below example:
<div id="app">
<validator name="validation1">
<form novalidate>
<h1>Survey</h1>
<fieldset>
<legend>Which do you like fruit ?</legend>
<input id="apple" type="radio" name="fruit" value="apple" v-validate:fruits="{
required: { rule: true, message: requiredErrorMsg }
}">
<label for="apple">Apple</label>
<input id="orange" type="radio" name="fruit" value="orange" v-validate:fruits>
<label for="orange">Orage</label>
<input id="grape" type="radio" name="fruit" value="grage" v-validate:fruits>
<label for="grape">Grape</label>
<input id="banana" type="radio" name="fruit" value="banana" v-validate:fruits>
<label for="banana">Banana</label>
<ul class="errors">
<li v-for="msg in $validation1.fruits.messages">
<p>{{msg}}</p>
</li>
</ul>
</fieldset>
</form>
</validator>
</div>
new Vue({
el: '#app',
computed: {
requiredErrorMsg: function () {
return 'Required fruit !!'
}
}
})
You can validate Selectbox. the below example:
<div id="app">
<validator name="validation1">
<form novalidate>
<select v-validate:lang="{ required: true }">
<option value="">----- select your favorite programming language -----</option>
<option value="javascript">JavaScript</option>
<option value="ruby">Ruby</option>
<option value="python">Python</option>
<option value="perl">Perl</option>
<option value="lua">Lua</option>
<option value="go">Go</option>
<option value="rust">Rust</option>
<option value="elixir">Elixir</option>
<option value="c">C</option>
<option value="none">Not a nothing here</option>
</select>
<div class="errors">
<p v-if="$validation1.lang.required">Required !!</p>
</div>
</form>
</validator>
</div>
new Vue({ el: '#app' })
You can grouping validation results. the below example:
<validator name="validation1" :groups="['user', 'password']">
username: <input type="text" group="user" v-validate:username="['required']"><br />
password: <input type="text" group="password" v-validate:password1="{ minlength: 8, required: true }"/><br />
password (confirm): <input type="text" group="password" v-validate:password2="{ minlength: 8, required: true }"/>
<div class="user">
<span v-if="$validation1.user.invalid">Invalid yourname !!</span>
</div>
<div class="password">
<span v-if="$validation1.password.invalid">Invalid password input !!</span>
</div>
</validator>
You can specify error message that can get the validation scope.
<validator name="validation1">
username: <input type="text" v-validate:username="{
required: { rule: true, message: 'required you name !!' }
}"><br />
password: <input type="text" v-validate:password="{
required: { rule: true, message: 'required you password !!' },
minlength: { rule: 8, message: 'your password short too !!' }
}"/><br />
<div class="errors">
<ul>
<li v-for="obj in $validation1.messages">
<div class="{{$key}}" v-for="msg in obj">
<p>{{$key}}: {{msg}}</p>
</div>
</li>
</ul>
</div>
</validator>
You can handle the valid
event and invalid
event. the below example:
new Vue({
el: '#app',
data: {
occuredValid: '',
occuredInvalid: ''
},
methods: {
onValid: function () {
this.occuredValid = 'occured valid event'
this.occuredInvalid = ''
},
onInvalid: function () {
this.occuredInvalid = 'occured invalid event'
this.occuredValid = ''
}
}
}
})
<div id="app">
<validator name="validation1">
comment: <input type="text" @valid="onValid" @invalid="onInvalid" v-validate:comment="[required]"/>
<div>
<p>{{occuredValid}}</p>
<p>{{occuredInvalid}}</p>
</div>
</validator>
</div>
When you will use lazy
attribute on validator
element directive, you allows initialization (compilation) of validator
element directive to wait for asynchronous data to be loaded.
The below component example:
<!-- comment component -->
<div>
<h1>Preview</h1>
<p>{{comment}}</p>
<validator lazy name="validation1">
<input type="text" :value="comment" v-validate:comment="{ required: true, maxlength: 256 }"/>
<span v-if="$validation1.comment.required">Required your comment</span>
<span v-if="$validation1.comment.maxlength">Too long comment !!</span>
<button type="button" value="save" @click="onSave" v-if="valid">
</validator>
</div>
Vue.component('comment', {
props: {
id: Number,
},
data: function () {
return { comment: '' }
},
activate: function (done) {
var resource = this.$resource('/comments/:id');
resource.get({ id: this.id }, function (comment, stat, req) {
this.commont = comment.body
// activate validator
this.$activateValidator()
done()
}.bind(this)).error(function (data, stat, req) {
// handle error ...
done()
})
},
methods: {
onSave: function () {
var resource = this.$resource('/comments/:id');
resource.save({ id: this.id }, { body: this.comment }, function (data, stat, req) {
// handle success
}).error(function (data, sta, req) {
// handle error
})
}
}
})
As above example, When asynchronous data loading finished, you need to call $activateValidator
meta method.
You can register your custom validator with using Vue.validator
. the below the exmpale:
// register custom validator
Vue.validator('email', function (val) {
return /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/.test(val)
})
new Vue({
el: '#app'
data: {
email: ''
}
})
<div id="app">
<validator name="validation1">
address: <input type="text" v-validate:address=['email']><br />
<div>
<span v-if="$validation1.address.email">invalid your email address format.</span>
</div>
<validator>
</div>
MEMO:
Vue.validator
asset has been extend from asset managment system of Vue.js.
You can register global error message together with custom validator. the below the exmpale:
// global error message with plain string
Vue.validator('numeric', {
message: 'invalid numeric value',
check: function (val) {
return /^[-+]?[0-9]+$/.test(val)
}
})
// global error message with function
Vue.validator('url', {
message: function (field) {
return 'invalid "' + field + '" url format field'
},
check: function (val) {
return /^(http\:\/\/|https\:\/\/)(.{4,})$/.test(val)
}
})
// build-in validator customizable
var required = Vue.validator('required')
Vue.validator('required', {
message: function (field) {
return 'required "' + field + '" field'
},
check: required,
})
<div id="app">
<validator name="validation1">
username: <input type="text" v-validate:username=['required']><br />
age: <input type="text" v-validate:age=['numeric']><br />
site: <input type="text" v-validate:site=['url']><br />
<div>
<p v-if="$validation1.username.required">{{ $validation1.username.messages.required }}</p>
<p v-if="$validation1.age.numeric">{{ $validation1.age.messages.numeric }}</p>
<p v-if="$validation1.site.url">{{ $validation1.site.messages.url }}</p>
</div>
<validator>
</div>
- async validation
- validate timing customize with options
- local asset registration (
compontents
asset-like) - server-side validation error applying
- more tests !!
- and other issues...
- Fork it !
- Create your top branch from
dev
:git branch my-new-topic origin/dev
- Commit your changes:
git commit -am 'Add some topic'
- Push to the branch:
git push origin my-new-topic
- Submit a pull request to
dev
branch ofvuejs/vue-validator
repository !
$ npm test