zoukankan      html  css  js  c++  java
  • AngularJS 表单数据验证及错误信息提示

    一、表单验证基本原理

      表单验证包括两个主题:

    • 定义验证规则,验证数据有效性。
    • 显示验证结果,把验证结果以友好的方式显示给用户。

      H5内置一些验证功能,并会显示内置的错误提示信息,先要禁用它,在<form>上加个novalidate特性。如下:

      <form ng-submit=vm.submit(vm.form)  novalidate="novalidate" >

      比如验证邮箱输入框input,验证两点,一是邮箱格式合法,二是必填。

      对于邮箱格式,AngularJS有个内置指令,只要设置input=email,接收输入的时候会检测格式是否合法,并设置有效性标志。

      对于必填,可以使用HTML自带的required,<input type="email" required="required"/>,可以使用AngularJS的ng-required,<input type="email" ng-required="true"/>,ng-required可以可以编程控制,其值可以是一个scope变量,<input type="email" ng-required="vm.needEmail"/>,而required这种HTML属性,出现就有效不管它有没有值。

      每次用户输入之后,这些验证器就会按照优先级和出现的顺序依次被验证,如果验证全部成功,就会把输入转换成Model中的值,如果有一个验证不成功,Model中的值保持原样,并在Model上增加一个$error对象,每一个验证器都会增加一个与验证器同名的属性,并值为true,如{email:true}。

      要在模板上引用,需要在form和input上都指定一个名字name,这样在$scope上就多出一个form变量,其内容如下:

       

      主要的几个变量解释如下:

      

      email字段的Model如下:

      

      与form的几个属性是一样的,意义也一样,这里,我们主要用到$dirty/$pristine、$valid/$invalid、$error,举个最简单的例子:

      

      字段多了,模板中会出现重复代码,可以用以下的错误信息提示指令解决该问题。

     二、错误信息提示指令 

    angular.module('com.ngnice.app').directive('bfFieldError',function bfFieldError($compile){
    
        return {
    
          restrict:'A',//必须以属性方式使用<input bf-field-error />
    
          require:'ngModel',//元素上必须有个ng-model属性,没有就会报错
    
          //link函数在指令初始化的时候自动执行
    
          link:function(scope,element,attrs,ngModel){//ngModel是require定义的值
    
            var subScope= scope.$new(true);//创建一个子作用域,true为独立作用域,不会父作用域自动继承属性
    
            //创建子作用域subScope下的两个函数
            //判断是否有错误,有错误就要显示错误信息
    
            subScope.hasError = function(){
    
              return ngModel.$invalid && ngModel.$dirty;//无效而且有输入才表示有错误
    
            };
    
            //获取错误信息内容,直接把错误信息显示到界面
    
            subScope.errors = function(){
    
              return ngModel.$error;
    
            }; 
    
            //把一段html编译成LiveDom,并把子作用域当参数传进去,DOM会根据subScope的变化更新自己
    
            var hint = $compile('<ul ng-if="hasError()">{{errors()}}</ul>')(subScope);//errors()内容是{email:true}
    
            //把这段DOM追加到当前元素后边,让他显示出来
            element.after(hint);
    
          }
    
        };
    
      });

      分析下,指令间协作配合机制,require属性指定另一个指令的名称,如上边的rquire:"ngModel",angularjs初始化的时候,会在指令所在元素寻找指令ng-model,并取得其控制器实例,并当作link函数的第四个参数传进去,就可以使用ngModel里边的属性了。

      改进html部分,用ng-repeat,而且用过滤器让提示信息更友好,见后边的过滤器

    var hint = $compile('<ul ng-if="hasError()"><li ng-repeat="(name,wrong) in errors()" ng-if="wrong">{{name|error}}</li></ul>')(subScope);

    三、友好提示信息的过滤器

      过滤器的实质是数据转换,格式化和筛选,这里是一个格式化函数,把Model层的数据类型转换成View层显示的友好信息。

     angular.module('com.ngnice.app').filter('error', function(){
    
        var messages={
          email:'不是有效的格式的邮件地址',
          required:'此项不能为空'
        };
        return function(name){
          return messages[name]||name;
        };
      });

      错误类型以后变更多,可以把message信息提取出去,建一个Constant,改造如下

      常量,专门用来存放提示信息

    angular.module('com.ngnice.app').constant('Error', {
        email:'不是有效的格式的邮件地址',
        required:'此项不能为空'
    });

      过滤器,把常量Error注入到过滤器 error中

    angular.module('com.ngnice.app').filter('error', function(Errors){
        return function(name){
            return Errors[name]||name;
     };
    });

     四、自定义验证规则指令

    1、密码相同验证指令

    angular.module('com.ngnice.app').directive('bfAssertSameAs',function bfAssertSameAs(){
    
        return {
    
          restrict:'A',
    
          require:'ngModel',
    
          link:function(scope,element,attrs,ngModel){
        
                  //取参数attrs传进来的bf-assert-same-as属性表达式,并用$eval,再比较两个值(还有个是参数传进去的值)是否相等。
            var isSame = function(value){
                        var anotherValue = scope.$eval(attrs.bfAssertSameAs);
                        return value === anotherValue;
               };
                   ngModel.$parsers.push(function(value){
                        ngModel.$setValidity('same',isSame(value));
                             return isSame(value) ? value : undefined;
                   });
                   scope.$watch(
                        function(){
                             return scope.$eval(attrs.bfAssertSameAs);
                         },
                         function(){
                              ngModel.$setValidity('same', isSame(ngModel.$modelValue));
                     }
                
          }
    
        };
    
      });                                                                      

       html部分,同时使用了bfFieldError指令

    <input id="_retypedPassword" bf-field-error type="password" ng-required="true" ng-model="vm.retypedPassword" bf-assert-same-as="vm.form.password"/>

      当确认密码和密码不同的时候,bf-field-error指令在检查结果中显示"same",看这句代码

     ngModel.$setValidity('same', isSame(ngModel.$modelValue));

     分析:

      $ngModel.$parsers是一个数组,当在输入框输入内容的时候,都会遍历并执行$parsers里面的函数。

      $ngModel.$setValidity("same",false);设置same为无效,会设置$ngModel.$error["same"] = false;  {"same" : false}

      可以在常量中添加一项:

    angular.module('com.ngnice.app').constant('Error', {
        email:'不是有效的格式的邮件地址',
        required:'此项不能为空',
        same:'此项必须与上一项相同'
    });

      到此时,通用性还不够好,可以进一步,修改bf-field-error指令,让自定义错误信息自己传进去,如下:

    <input id="_retypedPassword" bf-field-error="{same:'确认密码必须与密码相同'}" type="password" ng-required="true" ng-model="vm.retypedPassword" bf-assert-same-as="vm.form.password"/>

      修改bf-field-error指令代码:

    subScope.customMessages=scope.$eval(attrs.bfFieldError);//取得一个自定义消息对象{same:'确认密码必须与密码相同'}
    //把自定义消息对象customMessages传给过滤器
    var hint = $compile('<ul ng-if="hasError()"><li ng-repeat="(name,wrong) in errors()" ng-if="wrong">{{name|error:customerMessages}}</li></ul>')(subScope);

      最后要修改下过滤器error:

    angular.module('com.ngnice.app').filter('error', function(Errors){
        return function(name, customMessages){
            var errors = angular.extend({},Errors,customMessages);
            return errors[name]||name;
     };
    });

      整个执行过程如下:

    • 用户输入
    • angular执行所有$parsers中的函数
    • 遇到$setValidity("xxoo",false);那么就会把xxoo当做一个key设置到$ngModel.$error["xxoo"]
    • 然后bf-field-error指令会ng-repeat $ngModel.$error
    • error会对错误信息转义
    • 最后显示错误的信息
  • 相关阅读:
    Hadoop Mapreduce分区、分组、二次排序过程详解
    hadoop的NullWritable
    CentOS7.0修改主机名(hostname)
    Linux下不重启永久修改hostname
    稀缺——我们是如何陷入贫穷与忙碌的
    slf4j log4j logback关系详解和相关用法
    使用logstash+elasticsearch+kibana快速搭建日志平台
    安装XAMPP时出现 unable to realloc 83886080 bytes
    ElasticSearch查询max_result_window问题处理
    后台CMS日志处理记录
  • 原文地址:https://www.cnblogs.com/shawnhu/p/8540801.html
Copyright © 2011-2022 走看看