angular中的表單數據自定義驗證

以前說過了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

相關文章
相關標籤/搜索