ngModel.$ parsers无法在指令中使用 [英] ngModel.$parsers not working in directive
问题描述
我想动态地将指令添加到表单元素(输入,选择,文本区域...)
I want to dynamically add directives to form elements (input,select,textarea...)
<div ng-app="app" ng-controller="ctrl">
<form form-validator>
<input type="text" ng-model="model1">
<input type="text" ng-model="model2">
<input type="text" ng-model="model3">
<textarea ng-model="model4"></textarea>
<select>
<option ng-model="model5" value="1">Name</option>
</select>
</form>
</div>
指令
var app=angular.module('app',[])
.controller('ctrl',function($scope){
})
.directive('formValidator',function($compile){
return{
restrict: 'A',
link: function(scope, elem, attrs){
//is it possible to do this with one line of code?
elem.find('input').attr('validate-field','');
elem.find('select').attr('validate-field','');
elem.find('textarea').attr('validate-field','');
$compile(elem.contents())(scope);
}
}
})
.directive('validateField',function(){
return{
restrict: 'A',
require:['^ngModel'],
link: function(scope, element, attr, ctrls){
var valid = false;
var ngModel = ctrls[0];
alert('before validation');
ngModel.$parsers.unshift(function (value){
alert('validating');
valid = validator(value);
ngModel.$setValidity('required', valid, ctrls);
return valid ? value : undefined;
});
}
}
});
上面的代码能够将validate-field
属性添加到表单元素:
The code above was able to add validate-field
attribute to form elements:
<input type="text" ng-model="model1" validate-field>
问题是未调用ngModel.$parsers.unshift
,已调用alert('before validation');
,但未调用alert('validating');
.
The problem is ngModel.$parsers.unshift
is not being called, alert('before validation');
is called but alert('validating');
is not being called.
我想念什么?
推荐答案
当前,正在编译所有子validateField
指令后,您正在formValidator
指令链接函数进行评估.因为link: function(){ .. }
函数被认为与postLink函数相同,所以在所有子scope
链接准备就绪后才调用该函数.您的情况也是如此.
Currently what happening is you formValidator
directive link function is evaluating after all child validateField
directive gets compiled. Because link: function(){ .. }
function is considered as same as postLink function, which gets called after all children scope
linking ready. Same thing is happening in your case.
因此,我想说的是确实要调用您的链接函数,以确保在指令被编译之前它将添加validate-fields
.为此,您需要使用preLink
函数.
So I'd say say that do call your link function to ensure that it will add validate-fields
before directive gets compile. For that you need to use preLink
function.
.directive('formValidator', function($compile) {
return {
restrict: 'A',
link: {
pre: function(scope, elem, attrs) {
elem.find('input').attr('validate-field', '');
elem.find('select').attr('validate-field', '');
elem.find('textarea').attr('validate-field', '');
$compile(elem.contents())(scope);
}
}
}
})
更好的版本是只编译一次父指令
More better version would be compile parent directive only once
.directive('formValidator', function($compile) {
return {
restrict: 'A',
compile: function(elem, attrs) {
elem.find('input').attr('validate-field', '');
elem.find('select').attr('validate-field', '');
elem.find('textarea').attr('validate-field', '');
//removed to avoid infinite directive compile
elem.removeAttr('form-validator');
var linkFn = $compile(elem);
return function(scope, element, attr) {
linkFn(scope);
}
}
}
})
这篇关于ngModel.$ parsers无法在指令中使用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!