zoukankan      html  css  js  c++  java
  • angular中的表单数据自定义验证

    之前说过了angular是如何给表单的数据进行基本的,常用的验证的:angular学习笔记(二十)-表单验证

    但是在实际工作中,这些验证是远远不够的,很多时候我们需要自定义一些验证规则,以及一些异步,需要向后台发送请求的验证.

    这篇文章就来讲解,如何自定义验证规则.

    同时,这篇文章还是angular指令中使用ngModelController中关于 $validators 属性和 $asyncValidators$pending 属性的详细讲解.

    首先,需要自定义指令,设置require属性为'?^ngModel',在指令的link函数中通过第四个参数ctrl,获取到ngModelController这个东西.

    ngModelController实例有两个对象,一个是 $validators对象,一个是 $asyncValidators对象.当我们需要添加自定义的同步验证规则时,使用$validators对象,当我们需要添加自定义的异步验证规则时,使用$asyncValidators对象.

    通过栗子来说明:

    html:

    <!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属性,否则也没有什么意义了...

    这个指令我们共验证三项,且在元素失去焦点的时候进行验证:

    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

     
  • 相关阅读:
    n皇后问题
    POJ2155 Matrix二维线段树经典题
    hiho一下 第六十六周
    hdu1754 I hate it线段树模板 区间最值查询
    hdu5481 Desiderium
    自增运算符
    hdu-1823 Luck and Love
    Oracle 函数大全
    对前台传过来的实体是否为空 进行为空校验的N种方法
    IOC和DI的区别详解
  • 原文地址:https://www.cnblogs.com/liulangmao/p/4118868.html
Copyright © 2011-2022 走看看