angular自定义验证 ngModel的一些理解

每次使用自定义校验都不记得具体详情,故而记录之

1、数据流向

初始化 ——>$formatters ——>modelValue——>用户操作——>viewValue——>$parser——>modelValue

$formatters 通过代码调用,根据return的值初始化viewValue(一般不会用上这个功能)

$parser 通过用户输入,根据return的值赋给modelValue(不返回输入值,modelValue和viewValue的值不同也是可以的,这是为了满足啥需求设计出的)

下面有个demo

 1 <html lang="en" ng-app="app">  
 2 <head>  
 3     <meta charset="UTF-8">  
 4     <title>parser_uppercase</title>  
 5     <script type="text/javascript" src="js/angular.min.js"></script>
 6     <script type="text/javascript">  
 7         var app = angular.module('app',[]);  
 8         app.controller('MyCtrl', function($scope){  
 9             $scope.name = 'kobe';  
10             $scope.changeName = function(){  
11                 $scope.name = $scope.newName;  
12             }  
13         });  
14         app.directive('myTag', function(){  
15             return {  
16                 restrict: 'A',  
17                 require: 'ngModel',  
18                 link: function(scope, ele, attrs, ctrl){  
19                     ctrl.$parsers.push(function(value){ 
20                         console.log('$parsers方法被调用');   
21                         value = value.toUpperCase();  
22                         return value;  
23                     });  
24                     ctrl.$formatters.push(function(value){  
25                         console.log('$formatters方法被调用');  
26                         value = value.toUpperCase();  
27                         return value;  
28                     });  
29                 }  
30             }  
31         })  
32     </script>  
33 </head>  
34 <body ng-controller="MyCtrl">  
35     <input type="text" my-tag ng-model="name"/>  
36     <Strong>ModelValue:{{name}}</Strong>  
37     <input type="text" ng-model="newName"/>  
38     <button ng-click="changeName()">ChangeName</button>  
39 </body>  
40 </html>  

2、常用的校验方式($parser VS $watch)

一般有两种,一种是用$parser,一种使用$watch

 1 app.directive('promotionName',function () {
 2     return {
 3         require: 'ngModel',
 4         link: function (scope, elm, attrs, ngModelController) {
 5             ngModelController.$parsers.push(function(viewValue) {
 6                  var reg = /^[u4e00-u9fa50-9A-Za-z]{1,20}$/ ;
 7                 if(!reg.test(viewValue)){
 8                   ngModelController.$setValidity("promotionName",false);  
 9                   ngModelController.$formatters.push(undefined);
10                   return undefined;
11                 }else{
12                    ngModelController.$setValidity("promotionName",true);  
13                    ngModelController.$formatters.push(viewValue);
14                    return viewValue;
15                 }
16                 
17             })
18         }
19     };
20 });

使用$watch(《angularJS权威指南》demo使用watch)

app.directive('passwordConfirm',function () {
    return {
        require: 'ngModel',
        link: function (scope, elm, attrs, ngModelController) {
            scope.$watch(attrs.ngModel,function (newValue,oldValue) {
              if(newValue!==scope.passwordInfo.password){
                 ngModelController.$setValidity("passwordConfirm",false);  
              }else{
                 ngModelController.$setValidity("passwordConfirm",true);  
              }
            })
        }
    };
});

$parse和$watch方式的优劣,没了解angularJS的内部源码,不能详尽分析,一句话

同步的使用$parse,涉及异步则使用$watch(我猜的)

原文地址:https://www.cnblogs.com/peace1/p/6958014.html