我为表单验证创建了一个角度验证器模块,无需在表单中包含ngMessages,一切都按预期工作。
但是我发现了一个我一直试图修复的错误。它与$compile
有关。
所以我有一个向表单元素添加属性的指令,这是通过使用$ compile服务实现的,但是,$ compile服务似乎会导致ng-click
出现不需要的行为,所以当ng-click
位于里面时这个表格被称为两次火灾;
这是指令和我正在做的事情:
angular.module('app',[])
.directive('validateForm',['$compile',
function($compile)
{
var addErrors = function(rules, form, ctrls, scope, config){
//code
};
return {
restrict: 'A',
require: ['^form'],
link: {
post: function(scope, element, attrs, ctrls){
var form = ctrls[0];
var config = scope.validator;
if(typeof config != 'object') return;
var rules = config['rules'];
var errors = [];
//-----
},
pre: function(scope, element, attrs, ctrls){
var elm = element.find('select, input, textarea').attr('validate-field','');
element.removeAttr("validate-form"); //remove the attribute to avoid indefinite loop
element.removeAttr("data-validate-form");
$compile(element.contents())(scope);
}
}
};
}
])
.controller('UserController',['$scope', function($scope){
$scope.title = 'Form Validator';
$scope.clickThings = function(value){
alert(value); //pops up twice means ng-click fires twice
}
}]);
表单标记:
<div ng-controller="UserController">
<form novalidate="" validate-form name="form" role="form">
<div class="form-group">
<input type="text" class="form-control" ng-model="first_name" name="first_name" />
</div>
<div class="form-group">
<input type="text" class="form-control" ng-model="last_name" name="last_name" />
</div>
<div class="form-group">
<input type="text" class="form-control" ng-model="email" name="email" />
</div>
<div class="form-group">
<input type="password" class="form-control" ng-model="password" name="password" />
</div>
<div class="form-group">
<input type="text" class="form-control" ng-model="country" name="country" />
</div>
<a type="button" class="btn btn-success" ng-click="clickThings('Submit Clicked')">Submit</a>
</form>
</div>
我创造了一个plunker: http://embed.plnkr.co/uIid4gczKxKI4rPOHqx7
答案 0 :(得分:1)
在尝试了不同的事情后,我意识到已经编译的ng-click
在第$compile(element.contents())(scope)
被调用时被编译。
要解决此问题,只需编译已更改/受影响的元素,即
elem = element.find('select, input, textarea').attr('validate-field','');
将$compile(element.contents())(scope)
替换为$compile(elem)(scope);
所以我最终得到了这个:
angular.module('app',[])
.directive('validateForm',['$compile',
function($compile)
{
var addErrors = function(rules, form, ctrls, scope, config){
//code
};
return {
restrict: 'A',
require: ['^form'],
link: {
post: function(scope, element, attrs, ctrls){
var form = ctrls[0];
var config = scope.validator;
if(typeof config != 'object') return;
var rules = config['rules'];
var errors = [];
//-----
},
pre: function(scope, element, attrs, ctrls){
var elem = element.find('select, input, textarea').attr('validate-field','');
element.removeAttr("validate-form"); //remove the attribute to avoid indefinite loop
element.removeAttr("data-validate-form");
$compile(elem)(scope);
}
}
};
}
])
.controller('UserController',['$scope', function($scope){
$scope.title = 'Form Validator';
$scope.clickThings = function(value){
alert(value); //pops up twice means ng-click fires twice
}
}]);
这里的工作人员:
答案 1 :(得分:0)
在预链接功能中使用$compile
的目的是什么?如果你只想在指令元素链接之前进行模板转换 ,你应该将ur代码放在指令编译中并取出$ compile。或者如果你想在链接子元素之后编译元素,你应该把你的代码放在post-link中。将$compile
放在预链接中会导致子元素的子节点被链接两次。
选择:
angular.module('app',[])
.directive('validateForm',['$compile',
function($compile)
{
var addErrors = function(rules, form, ctrls, scope, config){
//code
};
return {
restrict: 'A',
require: ['^form'],
compile:function(element, attrs, ctrls){
// the code will be executed before get complied
var elm = element.find('select, input, textarea').attr('validate-field','');
return function(scope, element, attrs, ctrls){
var form = ctrls[0];
var config = scope.validator;
if(typeof config != 'object') return;
var rules = config['rules'];
var errors = [];
//-----
}
}
};
}
])
或者
angular.module('app',[])
.directive('validateForm',['$compile',
function($compile)
{
var addErrors = function(rules, form, ctrls, scope, config){
//code
};
return {
restrict: 'A',
require: ['^form'],
link: {
post: function(scope, element, attrs, ctrls){
var form = ctrls[0];
var config = scope.validator;
if(typeof config != 'object') return;
var rules = config['rules'];
var errors = [];
//-----
var elm = element.find('select, input, textarea').attr('validate-field','');
element.removeAttr("validate-form"); //remove the attribute to avoid indefinite loop
element.removeAttr("data-validate-form");
$compile(element.contents())(scope);
},
pre: function(scope, element, attrs, ctrls){
}
}
};
}
])
只需消除$compile
子句也可以。但这三种方式有一些区别。
有关更多信息,请参阅the official document