rizqidjamaluddin / vue-validator

Validator component for VueJS

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

vue-validator

Build Status CircleCI Status Coverage Status Sauce Test Status Commitizen friendly

Validator component for Vue.js

Requirements

  • Vue.js 1.0.10+

NOTE

vue-validator is still alpha verison. Maybe, There are some breaking change. If you have some feedback, we are welcome in Vue.js Discussion 😺

Installation

npm

stable version

$ npm install vue-validator

development version

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.

CDN

jsdelivr

<script src="https://cdn.jsdelivr.net/vue.validator/2.0.0-alpha.9/vue-validator.min.js"></script>

Usage

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.

Validation result structure

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.

Field validation properties

  • valid: whether field is valid. if it's valid, then return true, else return false.
  • invalid: reverse of valid.
  • touched: whether field is touched. if field was focused, return true, else return false.
  • untouched: reverse of touched.
  • modified: whether field value is modified. if field value was changed from initial value, return true, else return false.
  • dirty: whether field value was changed at least once. if so, return true, else return false.
  • pristine: reverse of dirty.
  • messages: if invalid field exist, return error message wrapped with object, else undefined.

Top level validation properties

  • valid: whether all fields is valid. if so, then return true, else return false.
  • invalid: if invalid field exist even one in validate fields, return true, else false.
  • touched: whether all fields is touched, if so, return true, else false.
  • untouched: if untouched field exist even one in validate fields, return true, else false.
  • modified: if modified field exist even one in validate fields, return true, else false.
  • dirty: if dirty field exist even one in validate fields, return true, else false.
  • pristine: whether all fields is pristine, if so, return true, else false.
  • messages: if invalid even one exist, return all field error message wrapped with object, else undefined.

Validator syntax

v-validate directive syntax the below:

    v-validate:field="array literal | object literal | binding"

Field

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>

caml-case property

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>

Literal

Array

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.

Object

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>

Binding

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.

Checkbox

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 !!'
    }
  }
})

Radio Button

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 !!'
    }
  }
})

Selectbox

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' })

Grouping

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>

Message

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>

Event

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>

Lazy initialization

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.

Custom validator

Registration

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.

Global error message

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>

TODO

  • async validation
  • validate timing customize with options
  • local asset registration (compontents asset-like)
  • server-side validation error applying
  • more tests !!
  • and other issues...

Contributing

  • 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 of vuejs/vue-validator repository !

Testing

$ npm test

License

MIT

About

Validator component for VueJS

License:MIT License


Languages

Language:JavaScript 90.0%Language:HTML 10.0%