zoukankan      html  css  js  c++  java
  • 自定义表单验证

      <input type="text" ng-model='li' fv>
    
    
    /*
      要使用link的第四个参数有两个必要条件
        1 require存在
        2 必须以属性或类名的方式存在于一个input标签中,并且该标签有ng-model属性;
    
     */
      app.directive('fv', function(){
        return {
          restrict: 'EA',
          require: 'ngModel',
          link: function(scope, ele, attr, ngmodel){
            console.info('lifei',ngmodel);
          }
        }
      })

    一下是输出的ngModel里面的内容
    1. NgModelController
      1. $asyncValidators:Object     异步验证
      2. $commitViewValue:()
      3. $dirty:false                                  是否修改
      4. $error:Object                                错误
      5. $formatters:Array[1]                      数据格式化的管道函数数组
      6. $invalid:false                                是否不合法
      7. $isEmpty:(value)                               是否是空
      8. $modelValue:undefined                     当前的valud值
      9. $name:""                                                                               input的name
      10. $options:null 
      11. $parsers:Array[0]                                                                 设置表单合法性的管道函数数组
      12. $pending:undefined
      13. $pristine:true
      14. $render:()
      15. $rollbackViewValue:()
      16. $setDirty:()                                                                          设置是否已修改
      17. $setPristine:()
      18. $setTouched:()
      19. $setUntouched:()
      20. $setValidity:setValidity(validationErrorKey, state, controller)         设置表单的某一验证的合法性
      21. $setViewValue:(value, trigger)                         设置valud值
      22. $touched:false
      23. $untouched:true
      24. $valid:true                                                验证时候合法
      25. $validate:()
      26. $validators:Object                                  同步验证
      27. $viewChangeListeners:Array[0]               当value值改变时,执行的管道函数数组
      28. $viewValue:undefined               当前input的ng-model的值
      29. __proto__:Object

    <form name='myForm'>
      <input type="text" name='li1' ng-model="lifei1">
      <input type="text" name="li2" pwd-match='myForm.li1' ng-model='lifei2'>
    </form>


      
    //判断两次输入的密码是否相同
    app.directive('myPwdMatch', [function(){ return {

    //如果用link的第四个参数ctrl,必须有require:'ngModel',和类型必须是属性 restrict:
    "A", require: 'ngModel', link: function(scope,element,attrs,ctrl){

    //attrs.myPwdMatch的属性值是formName.input1Name字符串,用scope.$eval()来解析字符串,获取对应的input1Name对象
    var tageCtrl = scope.$eval(attrs.myPwdMatch);

    //添加自定义表单验证的合法性 tageCtrl.$parsers.push(
    function(viewValue){

    //设置当前input的pwdmatch的合法性,如果input1的value值 等于当前input的value值,认为他合法 ctrl.$setValidity(
    'pwdmatch', viewValue == ctrl.$viewValue); return viewValue; });

    //当前input添加表单验证的合法性 ctrl.$parsers.push(
    function(viewValue){ if(viewValue == tageCtrl.$viewValue){ ctrl.$setValidity('pwdmatch', true); return viewValue; } else{ ctrl.$setValidity('pwdmatch', false); return undefined; } }); } }; }]);

    也就是说: $validators和$asyncValidators这两个管道是$parsers管道函数数组里面的其中两个比较特殊的管道;

    *5. $validators

    一个json对象.

    {
       validateName: function(modelValue,viewValue){
           return ...
       }
    }

    当$setViewValue(value)被赋值给$modelValue之前,会经过$parsers管道,经过$parsers管道时,就会经过这个$validators管道.其中validateName是验证的名字,函数是这个验证的方法,其中的参数modelValue和viewValue就是$modelValue和$viewValue,如果返回值是true,则通过validateName

    验证,如果返回值是false,则没有通过validateName验证,如果没有通过validateName验证,$error.validateName就会为true.这就是angular内部验证表单项的原理.

    eg: 自定义一个验证规则,输入内容中必须包含数字

    <div class="alert alert-danger" role="alert" ng-show="myForm.myWidget.$error.validCharacters">
        <strong>Oh!</strong> 不符合自定义的验证规则!
    </div>
    ngModel.$validators.validCharacters = function(modelValue, viewValue) {
        var value = modelValue || viewValue;
        return /[0-9]+/.test(value);
    };

    *6.$asyncValidators

    一个json对象.用来处理异步验证(比如一个http请求). 

    {
       validateName: function(modelValue,viewValue){
           return promise
       }
    }

    其中validateName是验证的名字,函数是这个验证的方法,其中的参数modelValue和viewValue就是$modelValue和$viewValue,返回值必须是一个promise对象,如果这个promise对象传递给它下一个.then方法失败通知,则不通过validateName验证,如果这个promise对象传递给它下一个.then方法成功通知,则表示通过validateName验证.当异步验证开始执行的时候,所有的异步验证都是平行并发的.只有当所有的验证都通过时,数据模型才会被同步更新.只要有一个异步验证没有完成,这个验证名就会被放到ngModelController的$pending属性中.另外,所有的异步验证都只会在所有的同步验证通过以后才开始.

    核心代码:

    <input validate-name type="text" name="myWidget" ng-model="userContent" ng-model-options="{updateOn:'blur'}" class="form-control" required uniqueUsername>
    
    <div class="alert alert-danger" role="alert" ng-show="myForm.myWidget.$error.uniqueUsername">
          <strong>Oh!</strong> 已经存在的用户名!
    </div>
    复制代码
    app.directive('validateName',function($http,$q){
        return {
            restrict:'A',
            require:'?^ngModel',
            link:function(scope,iele,iattr,ctrl){
                ctrl.$asyncValidators.uniqueUsername = function(modelValue, viewValue) {
                    var value = modelValue || viewValue;
                    // 异步验证用户名是否已经存在
                    return $http.get('/api/users/' + value).
                    then(function resolved(res) {
                        if(res.data){
                            //用户名已经存在,验证失败,给下一个promise传递失败通知.
                            return $q.reject('res.data');
                        }
                        else {
                            //用户名不存在,验证成功.
                            return true
                        }
    
                    }, function rejected() {
                            //请求失败
                    })
                };
            }
        }
    });
    复制代码

    一个指令用于异步验证是否重命名:

        /*异步验证是否重命名
        *     例子: <input type="text"   name="name" ng-model="form.name" create-head='{"url":"app_name/used","param":"app_name={value}"}'/>
        
        1 自定义验证: require,属性
            1 restrict必须是属性,requre必须是'ngModel'
        2 进行异步验证设置 $asyncValidators = {验证名: 验证函数}
        2 获取请求的url,用于ajax请求
            1 用先把input标签上的createHead属性的json字符串获取
            2 再用angular.formJson()解析成json对象
            3 再用string.replace(string,value),把占位符"{value}" 替换成input的modelValue值(scope上的值)
            4 用commonService来拼接url
        3 创建一个defered对象,用来返回状态
            1 用var a = $q.defer()创建
            2 a.reject()表示拒绝
            3 a.resolve()表示成功
        4 $http请求
            1 method,url,headers
            2 返回的是一个promise对象
        5 分情况验证
            1 如果成功,说明找到了,命名重复,验证不通过,返回a.reject();
            2 如果404,说明没找到了,命名不重复,验证通过,返回a.resolve();
            3 如果是其他情况,不能确定,是否重命名,按验证不通过算,赶回a.reject();
        6 返回一个promise对象
        * */
    
    app.directive("createHead", ["$q", "$http", "$cookies", "AppConfig", "commonService", function($q, $http, $cookies, AppConfig, commonService){
        return{
            restrict:"A",
            require:"ngModel",
            scope:{
                version:"="
            },
            link:function(scope,ele,attrs,ctl){
                console.info("ctrl",ctl);
                //格式demo:  create-head='{"url":"app_name/used","param":"app_name={value}"}'
                ctl.$asyncValidators.checkasync = function(modelValue,viewValue){
                    var d = $q.defer();
                    //angular.formJson()方法可以把json字符串解析成json对象;
                    var _a = angular.fromJson(attrs.createHead);
    
                    _a.url = _a.url.replace("{value}",modelValue);
                    if(_a.param){
                        _a.param = _a.param.replace("{value}",modelValue);
                    }
    
                    $http({
                        method:"HEAD",
                        url:commonService.getServerAuthUrl(_a.url,_a.param?_a.param:null),
                        headers:{
                            "Authorization": $cookies.get("token")
                        }
                    }).then(function(e){
                        //200 已存在
                        d.reject();
                    },function(e){
                        if(e.status==404){
                            //不存在
                            d.resolve();
                        }
                        else{
                            d.reject();
                        }
                    });
                    return d.promise;
                };
            }
        };
    }]);
  • 相关阅读:
    Java中接口对象实现回调
    推荐算法之计算相似度
    mahout入门实例2-Mahout单机开发环境介绍(参考粉丝日志)
    mahout入门实例-基于 Apache Mahout 构建社会化推荐引擎-实战(参考IBM)
    windows下gvim使用及常见命令
    一道C语言的问题(转)
    android开发手记一
    数据结构之有关图的算法(图的邻接表示法)
    Week of Code:GG
    HDU 5587:Array
  • 原文地址:https://www.cnblogs.com/bridge7839/p/6567184.html
Copyright © 2011-2022 走看看