每次使用自定义校验都不记得具体详情,故而记录之
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(我猜的)