«

»

angular表单验证$parsers和$validators方式区别

快抢沙发

这里只以表单里面的“输入密码”和“确认密码”为例,来看一下再angular1.3之前用的$parsers和1.3之后新增的$validators数组实现验证的方法区别。
先来看看HTML代码部分

<!-- 密码型字段 -->
	<div>
		<label for="_password">密码</label>
		<input type="password" id="_password" name="password" ng-model="vm.form.password" ng-required="true">
	</div>
	<div>
		<label for="_retypedPassword">确认密码</label>
		<input type="password" id="_retypedPassword" ng-model="vm.retypedPassword" bf-field-error bf-assert-same-as="vm.form.password">
	</div>

里面的bf-field-error指令是用来显示错误消息的,而bf-assert-same-as是特地为“确认密码”新增的指令,用来提示“两次的输入密码不符”的错误提示。
下面是指令bf-field-error的代码

.directive('bfFieldError', function($compile){
	return {
		restrict: 'A',
		require: 'ngModel',
		link: function(scope, ele, att, ngModelCtrl){
			//创建一个独立作用于的子scope
			var subScope = scope.$new(true);
			subScope.hasError = function(){
				//除了判断是否无效外,还要判断是否已经输入过
				return ngModelCtrl.$invalid && ngModelCtrl.$dirty;
			};
			subScope.errors = function(){
				//先直接显示到界面上,回头再改进为用户友好的方式
				return ngModelCtrl.$error;
			};
			//把一段HTML编译成"活dom",然后把subScope传递给它,这个"活dom"将会跟随subScope的变化自动更新自己
			var hint = $compile('<ul class="bf-field-error" ng-if="hasError()"><li ng-repeat="(name, wrong) in errors()" ng-if="wrong">{{name | errors}}</li></ul>')(subScope);
			//把这段"活dom"追加到当前元素后面,好让它显示出来
			ele.after(hint);
		}
	};
})

接着是我们的主角bf-assert-same-as

.directive('bfAssertSameAs', function(){
	return {
		restrict: 'A',
		require: 'ngModel',
		link: function(scope, ele, att, ngModelCtrl){
			var isSame = function(value){
				//取对照值,通过scope.$eval把att.bfAssertSameAs作为一个表达式在当前作用域中求值,否则它只是一个固定的字符串
				var anotherValue = scope.$eval(att.bfAssertSameAs);
				return value === anotherValue;
			};
			
			 //1.2.x只能用$parsers实现验证
			 ngModelCtrl.$parsers.push(function(value){
			 	//调用$setValidity设置验证结果,第一个参数是名字,和$error中的属性名一致,但是取值相反,因为这里表示的是“有效”,而$error中表示“无效”
			 	ngModelCtrl.$setValidity('same', isSame(value));
			 	return true;
			 });
			 // 这是assertSameAs验证器所特有的,因为当对照值(即vm.form.password)发生变化时,也要更新有效性状态
			 scope.$watch(function(){
			 	return scope.$eval(att.bfAssertSameAs);
			 }, function(){
			 	//变化时重新判断并设置验证结果
			 	ngModelCtrl.$setValidity('same', isSame(ele.val()));
			});
		}
	};
})

需要注意的是$setValidity的返回值为 undefined或者false时会在 $error里面会存在parse:true的问题,上面选择了直接返回true
如果用最新的$validators数组则应该这样写,他需要返回布尔类型的值

.directive('bfAssertSameAs', function(){
	return {
		restrict: 'A',
		require: 'ngModel',
		link: function(scope, ele, att, ngModelCtrl){
			var isSame = function(value){
				//取对照值,通过scope.$eval把att.bfAssertSameAs作为一个表达式在当前作用域中求值,否则它只是一个固定的字符串
				var anotherValue = scope.$eval(att.bfAssertSameAs);
				return value === anotherValue;
			};
                        //1.3.x增加了专门的$validators数组,可用更好的方式实现验证。这里个数组都是放需要被执行的函数的                        
			ngModelCtrl.$validators.same = function(value){ //返回值必须是boolean类型
				//调用$setValidity设置验证结果,第一个参数是名字,和$error中的属性名一致,但是取值相反,因为这里表示的是“有效”,而$error中表示“无效”
				return isSame(value);
			};
			// 这是assertSameAs验证器所特有的,因为当对照值(即vm.form.password)发生变化时,也要更新有效性状态
			scope.$watch(function(){
				return scope.$eval(att.bfAssertSameAs);
			}, function(newValue){
				
				//变化时重新判断并设置验证结果
				ngModelCtrl.$setValidity('same', isSame(ele.val()));
			});
		}
	};
})

效果如下:baidushurufa_2016-10-21_18-25-20

2016.10.21
H
阅读全文...

AngularJS的controllerAs常见用法

快抢沙发

我们一般用controllerAs多半是因为要用到我们的controller里面的数据,比如获取一个名叫cells.json,里面包含了所有手机的概况,我们需要获取这些数据以便ng-repeate它,一般我们可以在路由和指令里面使用。
先上模板页面cells.html

<ul>
	<li ng-repeat="cell in vm.cells">{{cell.name}},价格:{{cell.price}}</li>
</ul>

路由内容

'use strict';

angular
.module('myApp', ['ngRoute', 'app.directive'])
.config(['$routeProvider', function($routeProvider) {
	$routeProvider
	.when('/', {
		template: 'index'
	})
	.when('/cells', {
		template: '<cells-list></cells-list>',
		controller: ['Cells', 
		    function (Cells) {
			var vm = this
                        vm.cells = Cells.query();
    	            }
                ],
		controllerAs: 'vm'
	})
}])

指令内容

'use strict';

angular
.module('app.directive',['app.service'])
.directive('cellsList', function(){
	return {
		templateUrl:'view/cells.html',
		controller: ['Cells', 
		   function (Cells) {
		      var vm = this
                      vm.cells = Cells.query();
    	           }
                ],
                controllerAs: 'vm'
	}
})

可以选择在路由里面用controller和controllerAs,或者在指令里面使用。

效果都是一样的
controller和controllerAs

2016.10.15
H
阅读全文...
  • sitemap_baidu