AngularJS实现表单手动验证和表单自动验证

AngularJS的表单验证大体有两种,一种是手动验证,一种是自动验证。
1、手动验证
所谓手动验证是经过AngularJS表单的属性来验证。而成为AngularJS表单必须知足两个条件:css

一、给form元素加上novalidate="novalidate";html

二、给form元素加上name="theForm",以下:node

<!DOCTYPE html>
< html  lang = "en"  ng-app = "myApp1" >
< head >
  < meta  charset = "UTF-8" >
  < title ></ title >
  < link  rel = "stylesheet"  href = "../node_modules/bootstrap/dist/css/bootstrap.min.css" />
  < link  rel = "stylesheet"  href = "../css/main.css" />
</ head >
< body >
< nav  >
  < div  class = "container" >
   < div  class = "navbar-header" >
    < a  href = "/"  class = "navbar-brand" >Form Submitting</ a >
   </ div >
  </ div >
</ nav >
  
< div  class = "container main-content"  ng-controller = "myCtrl1" >
  <!--novalidate让表单不要使用html验证-->
  <!--theForm变成scope的一个字段-->
  < form  ng-submit = "onSubmit(theForm.$valid)"  novalidate = "novalidate"  name = "theForm" >
   < div  class = "form-group" >
    < label  for = "name" >Name</ label >
    < input  type = "text"  class = "form-control"  id = "name"  ng-model = "formModel.name" />
   </ div >
  
   < div  class = "form-group"  ng-class="{
    'has-error': !theForm.email.$valid && (!theForm.$pristine || theForm.$submitted),
    'has-success': theForm.email.$valid && (!theForm.$pristine || theForm.$submitted)
    }">
    < label  for = "email" >Email</ label >
    < input  type = "email"  class = "form-control"  id = "email"  ng-model = "formModel.email"  required = "required"  name = "email" />
    < p  class = "help-block"  ng-show = "theForm.email.$error.required && (!theForm.$pristine || theForm.$submitted)" >必填</ p >
    < p  class = "help-block"  ng-show = "theForm.email.$error.email && (!theForm.$pristine || theForm.$submitted)" >email格式不正确</ p >
   </ div >
  
   < div  class = "form-group" >
    < label  for = "username" >Username</ label >
    < input  type = "text"  class = "form-control"  id = "username"  ng-model = "formModel.username" />
   </ div >
  
   < div  class = "form-group" >
    < label  for = "age" >Age</ label >
    < input  type = "number"  class = "form-control"  id = "age"  ng-model = "formModel.age" />
   </ div >
  
   < div  class = "form-group" >
    < label  for = "sex" >Sex</ label >
    < select  name = "sex"  id = "sex"  class = "form-control"  ng-model = "formModel.sex" >
     < option  value = "" >Please choose</ option >
     < option  value = "male" >Mail</ option >
     < option  value = "femail" >Femail</ option >
    </ select >
   </ div >
  
   < div  class = "form-group" >
    < label  for = "password" >Password</ label >
    < input  type = "text"  class = "form-control"  id = "password"  ng-model = "formModel.password" />
   </ div >
  
   < div  class = "form-group" >
    < button  class = "btn btn-primary"  type = "submit" >Register</ button >
   </ div >
  
    < pre >
     {{theForm | json}}
    </ pre >
  </ form >
</ div >
< script  src = "../node_modules/angular/angular.min.js" ></ script >
< script  src = "second.js" ></ script >
</ body >
</ html >

● 给form加上novalidate="novalidate"意味着表单将再也不使用HTML5验证特性
● 给form加上name="theForm"意味着表单的名称是theForm。如何使用theForm,好比咱们验证表单是否被修改过theForm.$submitted
● 经过ng-submit提交表单
● formModel是$scope中的一个属性
● 对表单的Email进行了手动验证,使用了AngularJS表单的众多属性,好比theForm.email.$valid,theForm.$pristine,theForm.$submitted, theForm.email.$error.required,theForm.email.$error.email
● 经过<pre>{{theForm | json}}</pre>把AngularJS表单的全部属性都打印出来
{
  "$error": {
   "required": [
    {
     "$validators": {},
     "$asyncValidators": {},
     "$parsers": [],
     "$formatters": [
      null
     ],
     "$viewChangeListeners": [],
     "$untouched": true,
     "$touched": false,
     "$pristine": true,
     "$dirty": false,
     "$valid": false,
     "$invalid": true,
     "$error": {
      "required": true
     },
     "$name": "email",
     "$options": null
    }
   ]
  },
  "$name": "theForm",
  "$dirty": false,
  "$pristine": true,
  "$valid": false,
  "$invalid": true,
  "$submitted": false,
  "email": {
   "$validators": {},
   "$asyncValidators": {},
   "$parsers": [],
   "$formatters": [
    null
   ],
   "$viewChangeListeners": [],
   "$untouched": true,
   "$touched": false,
   "$pristine": true,
   "$dirty": false,
   "$valid": false,
   "$invalid": true,
   "$error": {
    "required": true
   },
   "$name": "email",
   "$options": null
  },
  "sex": {
   "$validators": {},
   "$asyncValidators": {},
   "$parsers": [],
   "$formatters": [],
   "$viewChangeListeners": [],
   "$untouched": true,
   "$touched": false,
   "$pristine": true,
   "$dirty": false,
   "$valid": true,
   "$invalid": false,
   "$error": {},
   "$name": "sex",
   "$options": null
  }
}
以上,凡有name属性的input都被显示在上面。
在second.js文件中定义了module,controller以及提交表单的方法。
var myApp1 = angular.module( 'myApp1' ,[]);
  
myApp1.controller( 'myCtrl1' , function ($scope, $http){
   $scope.formModel = {};
  
   $scope.onSubmit = function (){
     $http.post( 'someurl' ,$scope.formModel)
       .success( function (data){
         console.log( ':)' );
       })
       .error( function (data){
         console.log( ':(' );
       });
  
     console.log($scope.formModel);
   };
});
 
以上的表单验证方式好处是可控性强,但相对繁琐。
2、自动验证
AngularJS的另一种表单验证方式是自动验证,即经过directive来实现,除了AngularJS自带的directive,还须要用到angular-auto-validate这个第三方module。
有关 angular-auto-validate:
● 安装:npm i angular-auto-validate
● 引用:<script src="../node_modules/angular-auto-validate/dist/jcs-auto-validate.min.js"></script>
● module依赖:var myApp = angular.module("app", ["jcs-autoValidate"]);
为了实现错误信息本地化,还须要 angular-localize这个第三方module:
● 安装:npm install angular-localize --save
● module依赖:var myApp = angular.module("app", ["localize"]);
● 引用:
<script src= "../node_modules/angular-sanitize/angular-sanitize.min.js" ></script>
<script src= "../node_modules/angular-localize/angular-localize.min.js" ></script>

此外,当点击提交表单按钮,须要禁用按钮并显示一种等待效果,须要用到angular-ladda这个第三方module:npm

● 安装:bower install angular-ladda --save
● module依赖:var myApp = angular.module("app", ["angular-ladda"]);
● 引用:json

<link rel= "stylesheet" href= "../bower_components/ladda/dist/ladda-themeless.min.css" />
<script src= "../bower_components/ladda/dist/spin.min.js" ></script>
<script src= "../bower_components/ladda/dist/ladda.min.js" ></script>
<script src= "../bower_components/angular-ladda/dist/angular-ladda.min.js" ></script>
页面以下:
<!DOCTYPE html>
< html lang = "en" ng-app = "myApp1" >
< head >
  < meta charset = "gb2312" >
  < title ></ title >
  < link rel = "stylesheet" href = "../node_modules/bootstrap/dist/css/bootstrap.min.css" />
  < link rel = "stylesheet" href = "../bower_components/ladda/dist/ladda-themeless.min.css" />
  < link rel = "stylesheet" href = "../css/main.css" />
</ head >
< body >
< nav >
  < div class = "container" >
   < div class = "navbar-header" >
    < a href = "/" class = "navbar-brand" >Form Validating Auto</ a >
   </ div >
  </ div >
</ nav >
  
< div class = "container main-content" ng-controller = "myCtrl1" >
  <!--novalidate让表单不要使用html验证-->
  <!--theForm变成scope的一个字段-->
  < form ng-submit = "onSubmit()" novalidate = "novalidate" >
   < div class = "form-group" >
    < label for = "name" class = "control-label" >Name</ label >
    < input type = "text" class = "form-control" id = "name" ng-model = "formModel.name" required = "required" />
   </ div >
  
   < div class = "form-group" >
    < label for = "email" class = "control-label" >Email</ label >
    < input type = "email" class = "form-control" id = "email" ng-model = "formModel.email" required = "required" />
  
   </ div >
  
   < div class = "form-group" >
    < label for = "username" class = "control-label" >Username</ label >
    < input type = "text"
        class = "form-control"
        id = "username"
        ng-model = "formModel.username"
        required = "required"
        ng-pattern = "/^[A-Za-z0-9_]{1,32}$/"
        ng-minlength = "7"
        ng-pattern-err-type = "badUsername"
     />
   </ div >
  
   < div class = "form-group" >
    < label for = "age" class = "control-label" >Age</ label >
    < input type = "number"
        class = "form-control"
        id = "age"
        ng-model = "formModel.age"
        required = "required"
        min = "18"
        max = "65"
        ng-min-err-type = "tooYoung"
        ng-max-err-type = "tooOld"
     />
   </ div >
  
   < div class = "form-group" >
    < label for = "sex" class = "control-label" >Sex</ label >
    < select name = "sex" id = "sex" class = "form-control" ng-model = "formModel.sex" required = "required" >
     < option value = "" >Please choose</ option >
     < option value = "male" >Mail</ option >
     < option value = "femail" >Femail</ option >
    </ select >
   </ div >
  
   < div class = "form-group" >
    < label for = "password" class = "control-label" >Password</ label >
    < input type = "text" class = "form-control" id = "password" ng-model = "formModel.password" required = "required" ng-minlength = "6" />
   </ div >
  
   < div class = "form-group" >
    <!--<button class="btn btn-primary" ng-click="onSubmit()">Register</button>-->
    < button class = "btn btn-primary"
        ladda = "submitting"
        data-style = "expand-right"
        type = "submit" >
     < span ng-show = "submitting" >正在注册...</ span >
     < span ng-show = "!submitting" >注册</ span >
    </ button >
   </ div >
  
    < pre >
     {{formModel | json}}
    </ pre >
  </ form >
</ div >
< script src = "../node_modules/angular/angular.min.js" ></ script >
  
< script src = "form_validation_auto.js" ></ script >
< script src = "../node_modules/angular-auto-validate/dist/jcs-auto-validate.min.js" ></ script >
< script src = "../node_modules/angular-sanitize/angular-sanitize.min.js" ></ script >
< script src = "../node_modules/angular-localize/angular-localize.min.js" ></ script >
  
< script src = "../bower_components/ladda/dist/spin.min.js" ></ script >
< script src = "../bower_components/ladda/dist/ladda.min.js" ></ script >
< script src = "../bower_components/angular-ladda/dist/angular-ladda.min.js" ></ script >

以上,先看提交按钮:bootstrap

< div  >
  <!--<button class="btn btn-primary" ng-click="onSubmit()">Register</button>-->
  < button  class = "btn btn-primary"
      ladda  "submitting"
      data-style = "expand-right"
      type = "submit" >
   < span  ng-show = "submitting" >正在注册...</ span >
   < span  ng-show = "!submitting" >注册</ span >
  </ button >
</ div >
 

● ladda属性值为bool值,true表示显示动态等待效果,false不显示动态等待效果,这里的submitting是scope中的一个属性
● data-style="expand-right"表示在按钮的右侧显示动态等待效果app

再拿表单中的Age字段来讲:less

< div >
  < label for = "age" class = "control-label" >Age</ label >
  < input type = "number"
      class = "form-control"
      id = "age"
      ng-model = "formModel.age"
      required = "required"
      min = "18"
      max = "65"
      ng-min-err-type = "tooYoung"
      ng-max-err-type = "tooOld"
   />
</ div >
其中,min, max为AgularJS的directive,而ng-min-err-type是angular-auto-validate的directive。这里遵循的惯例是ng-AngularJS表单验证的directive名称-err-type,而tooYoung和tooOld的做用是什么,又是在哪里用上了呢?
是在module层面用上了,定义在了form_validation_auto.js文件中。
 
var  myApp1 = angular.module( 'myApp1' ,[ 'jcs-autoValidate' , 'localize' , 'angular-ladda' ]);
  
myApp1.run( function (defaultErrorMessageResolver){
   defaultErrorMessageResolver.getErrorMessages().then( function (errorMessages){
     errorMessages[ 'tooYoung' ] =  '年龄必须小于{0}' ;
     errorMessages[ 'tooOld' ] =  '年龄不能大于{0}' ;
     errorMessages[ 'badUsername' ] =  '用户名只能包含数字、字母或下划线' ;
   });
});
  
myApp1.controller( 'myCtrl1' function ($scope, $http){
   $scope.formModel = {};
   $scope.submitting =  false ;
  
   $scope.onSubmit =  function (){
  
     $scope.submitting =  true ;
     console.log( '已提交' );
     console.log($scope.formModel);
  
     $http.post( 'url' ,$scope.formModel)
       .success( function (data){
         console.log( ':)' );
         $scope.submitting =  false ;
       })
       .error( function (data){
         console.log( ':(' );
         $scope.submitting =  false ;
       });
   };
});
以上,在run方法中使用angular-auto-validate的defaultErrorMessageResolver服务,对错误信息进行为了自定义。
页面上的tooYoung和tooOld和这里的errorMessages['tooYoung']和errorMessages['badUsername']对应。