2018年2月3日 星期六

[Vue] Custom validator with vue-form

  Vue.js    vue-form     validator


Introduction


vue-form is for form validation for Vue.js 2.2+.
We will create a custom validator with it as a sample in this article.


Environment


vue.js 2.5.13
bootstrap 4.0.0
vue-form 4.7.1



Implement


Use default validator

After installing vue-form and bootstrap, simply import and initialize it as following.

JS

Vue.use(VueForm);

var app = new Vue({
    el: '#app',
    data: {
        me: { name:
'', email: '' }, //my model
        formstate: {} //vue-form state
    },
    methods: {
        //Form validation class
        fieldClassName: function (field) {
            if (!field) {
                return '';
            }
            if ((field.$touched || field.$submitted) && field.$valid) {
                return 'is-valid';
            }
            if ((field.$touched || field.$submitted) && field.$invalid) {
                return 'is-invalid';
            }
        }
    }
})



HTML

Here we create a sample for validating the required input element.

<div id="app">
    <vue-form :state="formstate" v-on:submit.prevent="submit">
       <label>Name*</label>
          <validate auto-label class="form-group required-field">
             <input type="text" name="name" required v-model="my.name" :class="fieldClassName(formstate.name)"/>
                <field-messages name="name" show="$touched || $submitted">
                   <span slot="required" class="badge badge-danger">Name is a must!</span>
                </field-messages>
           </validate>
</vue-form>
</div>

There are three parts:
<vue-form> <validate><field-messages>


<vue-form>

Defines the scope of the form.


<validate>

We put our form controls in <validate> to make vue-form enable the default validators on it.


<field-messages>

Display the validation result for the mapped element’s name, “name”, in this sample code.
Use
show="$touched || $submitted" to determine whether show it or not by field’s current state. You can replace the condition with the following states.

$dirty
$pristine
$valid
$invalid
$touched
$untouched
$focused
$submitted
$pending



Result




Create Custom validator

Now we are going to create a custom validator in order to block a user from creating a duplicate name in the database.


JS

First we create a validator: notDuplicateKey, which result from a validation function: checkDuplicateKey.

Vue.use(VueForm);

var app = new Vue({
    el: '#app',
    data: {
        me: { name:
'', email: '' }, //my model
        notDuplicateKey: true,
        formstate: {} //vue-form state
    },
    methods: {
        //Form validation class
        fieldClassName: function (field) {
            //Skip…
        },
       
//Chekc if the key exists in backend
         checkDuplicateKey: function (event, key) {
            var vm = this;
            axios.get(vm.$checkIsDuplicateKeyUri + decodeURIComponent(key))
                .then(function (response) {
                    vm.notDuplicateKey = !response.data;
                }, function (error) {

                });
        }
    }
})



Notice that the custom validator could be a computed data or a function, and you can register it as a global validator.

HTML

Update html as following.

<div id="app">
    <vue-form :state="formstate" v-on:submit.prevent="submit">
       <label>Name*</label>
          <validate auto-label class="form-group required-field"
:custom="{'not-duplicate-key': notDuplicateKey}" >
             <input type="text" name="name" required v-model="my.name" :class="fieldClassName(formstate.name)"
             
v-on:blur="checkDuplicateKey($event, me.name)"
/>
                <field-messages name="name" show="$touched || $submitted">
                   <span slot="required" class="badge badge-danger">Name is a must!</span>
                   <
span slot="not-duplicate-key" class="badge badge-danger">Duplicate name!</span>
                </field-messages>
           </validate>
</vue-form>
</div>


<validate>

<validate :custom="{'not-duplicate-key': notDuplicateKey}"></validate>

'not-duplicate-key' is the slot name for field message. And we use notDuplicateKey as the custom validator.


<field-messages>

<span slot="not-duplicate-key" class="badge badge-danger">Duplicate name!</span>

In field messages, we add a new one for validator: notDuplicateKey, which had the mapping slot name: not-duplicate-key


At last, we need to update the validator by binding the blur event on input dom.
<input type="text" name="name" required v-model="my.name" :class="fieldClassName(formstate.name)" v-on:blur="checkDuplicateKey($event, me.name)" />

If you want to check if it’s a duplicate name while user key in every character, bind the validation function to keyup event.


Demo



Reference





沒有留言:

張貼留言