以前说过了angular是如何给表单的数据进行基本的,经常使用的验证的:angular学习笔记(二十)-表单验证css
可是在实际工做中,这些验证是远远不够的,不少时候咱们须要自定义一些验证规则,以及一些异步,须要向后台发送请求的验证.html
这篇文章就来说解,如何自定义验证规则.node
同时,这篇文章仍是angular指令中使用ngModelController中关于 $validators 属性和 $asyncValidators 和 $pending 属性的详细讲解.git
首先,须要自定义指令,设置require属性为'?^ngModel',在指令的link函数中经过第四个参数ctrl,获取到ngModelController这个东西.github
ngModelController实例有两个对象,一个是 $validators对象,一个是 $asyncValidators对象.当咱们须要添加自定义的同步验证规则时,使用$validators对象,当咱们须要添加自定义的异步验证规则时,使用$asyncValidators对象.express
经过栗子来讲明:bootstrap
html:api
<!DOCTYPE html> <html ng-app="customControl"> <head> <title>asyncValidators</title> <meta charset="utf-8"> <script src="angular-1.3.2.js"></script> <script src="script.js"></script> <link type="text/css" href="bootstrap.css" rel="stylesheet" /> <style> *{font-family: 'MICROSOFT YAHEI'} </style> </head> <body> <div class="container" ng-controller="ctrl"> <div class="page-header"> <h1>ngModelController- <small>asyncValidators实现异步验证表单</small></h1> </div> <form role="form" name="myForm"> <div class="form-group"> <input validate-name type="text" name="myWidget" ng-model="userContent" ng-model-options="{updateOn:'blur'}" class="form-control" required> </div> <div class="alert alert-danger" role="alert" ng-show="myForm.myWidget.$error.required"> <strong>Oh!</strong> 必填! </div> <div class="alert alert-danger" role="alert" ng-show="myForm.myWidget.$error.validCharacters"> <strong>Oh!</strong> 不符合自定义的验证规则! </div> <div class="alert alert-danger" role="alert" ng-show="myForm.myWidget.$error.uniqueUsername"> <strong>Oh!</strong> 已经存在的用户名! </div> </form> <div class="panel panel-primary"> <div class="panel-heading"> <h3 class="panel-title">用户名:</h3> </div> <div class="panel-body"> {{userContent}} </div> </div> <div class="panel panel-primary"> <div class="panel-heading"> <h3 class="panel-title">正在异步验证中:</h3> </div> <div class="panel-body"> {{myForm.myWidget.$pending}} </div> </div> </div> </body> </html>
这段html里,input元素使用了validate-name这个指令,后面在js中咱们会经过这个指令来给它添加验证.注意元素必需要有ng-model属性,不然也没有什么意义了...promise
这个指令咱们共验证三项,且在元素失去焦点的时候进行验证:app
1.required : ng内置的的验证,须要在指令的最后添加required属性. 而后本身指令里什么也不用写,就能够验证它是否为空了.
2.validCharacters: 自定义的一个同步验证规则,验证输入的内容是否包含'bunny'字符串,自定义的验证不须要在指令最后添加validCharacters属性
3.uniqueUsername: 自定义的一个异步验证规则,验证输入的用户名是否已经被注册,一样,自定义的规则不须要在指令的最后添加uniqueUsername属性
而后来看js代码:
var app = angular.module('customControl',[]); app.controller('ctrl',function($scope){ }); app.directive('validateName',function($http,$q){ return { restrict:'A', require:'?^ngModel', link:function(scope,iele,iattr,ctrl){ ctrl.$validators.validCharacters = function(modelValue, viewValue) { var value = modelValue || viewValue; return value ? value.indexOf('bunny')!==-1 : true }; ctrl.$asyncValidators.uniqueUsername = function(modelValue, viewValue) { var value = modelValue || viewValue; // Lookup user by username return $http.get('/api/users/' + value). then(function resolved(res) { if(res.data){ //用户名已经存在,验证失败,给下一个promise传递失败通知. return $q.reject('res.data'); } else { //用户名不存在,验证成功. return true } }, function rejected() { }) }; } } });
先说 validCharacters 验证: 咱们给ctrl(也就是ngModelController的实例)的$validators属性添加了validCharacters属性,它的属性值为一个函数,函数接受两个参数modelValue和viewValue,这两个参数具体分别表明什么,请入angular指令中使用ngModelController查看,总之,这里能够认为就是input的value值.而后咱们经过这个自定义的函数的返回值来肯定是否经过验证,若是是true,则经过验证,若是是false,则不经过验证,在不经过验证的时候,$error.validCharacters就会为true.
同理,来看uniqueUsername 验证:咱们给ctrl的$asyncValidators属性添加了uniqueUsername属性,它的属性值为一个函数,函数接受的参数也同上,而后咱们经过$http发送请求来验证用户名是否存在:
node代码:
var express = require('express'); var app = express(); app.use(express.static(__dirname+'')); app.use(express.bodyParser()); app.use(express.methodOverride()); var names = [ 'code_bunny','mi_bunny','hua_bunny' ]; app.get('/api/users/:name',function(req,res){ setTimeout(function(){ var name = req.params.name; names.forEach(function(list){ if(name==list) { res.send(list); } else { res.end() } }); },1000); }); app.listen(9000);
咱们故意延迟了1000毫秒再给出响应,这样,在等待响应的时间里,咱们能够看到myForm.myWidget.$pending发生的变化:
当获得响应后,它就会变为空.
因此,$pending属性里放置的是因此正在等待响应的异步验证.
最重要的一点,$asyncValidators的验证函数返回值好比是一个promise对象.根据这个promise对象发出的通知来决定验证是成功仍是失败.若是发出的是失败通知,那么它就是验证失败,好比这里的$q.reject().若是发出的是成功经过,那么他就是验证成功,好比这里的return false.
这里要注意promise的用法:因为$http.get()返回的promise,不管执行的是resolved函数仍是rejected函数,他发送给下一个promise的通知老是成功的,因此为了发送失败通知,必须使用$q.reject().
另外,我原本想尝试若是能搜索到用户名,则返回搜索到的用户名,若是不能,则不返回,让它接收到404状态,而后调用rejected函数,可是没能成功,由于若是不返回,它会请求很长一段时间才算请求失败,而不是一旦发现找不到就马上算请求失败了.因此这里仍是根据搜索结果返回不一样值来进行判断.
完整代码: https://github.com/OOP-Code-Bunny/angular/tree/master/ngModelController/asyncValidators