当我编译包含该指令的元素时,我发现指令的行为不一致。在我的情况下,我有一个指令,验证密码是否与另一个密码字段匹配。该指令如下所示:
app.directive('passwordMatches', function() {
return {
require: 'ngModel',
restrict: 'A',
scope: {
otherPasswordFieldValue: '=passwordMatches'
},
link: function (scope, elem, attrs, ngModelController) {
function validate(value) {
return value === scope.otherPasswordFieldValue;
}
//For DOM -> model validation
ngModelController.$parsers.unshift(function (value) {
var valid = validate(value);
ngModelController.$setValidity('password-matches', valid);
return valid ? value : undefined;
});
//For model -> DOM validation
ngModelController.$formatters.unshift(function (value) {
ngModelController.$setValidity('password-matches', validate(value));
return value;
});
scope.$watch(function() { return scope.otherPasswordFieldValue }, function () {
var valid = validate(ngModelController.$viewValue);
ngModelController.$setValidity('password-matches', valid);
});
}
};
});
这一切都很好。但是我有另一个经常在同一个元素上使用的指令。该指令的细节并不重要,因为我已经证明问题的根本原因是第二个指令编译元素。一旦我添加此指令,行为就会改变。在没有编译元素的情况下,我的passwordMatches指令工作正常(如果我输入的内容与其他字段不匹配,则字段变为无效,我可以输入我想要的任何内容)。
但是一旦我编译元素,我就可以输入我想要的内容,直到我使字段匹配并且它在此之前表现正常。但是,一旦两个字段中的值匹配,如果我键入任何内容以使它们不匹配,则该字段将完全消隐。查看此内容的最简单方法是使用此jsbin:http://jsbin.com/IkuMECEf/12/edit。要重现,请键入" foo"在第一个字段中,然后尝试键入" fooo" (三个o)在第二个领域。只要你键入第三个" o"这个领域被淘汰了。如果你注释掉$ compile,它就可以了。
谢谢!
答案 0 :(得分:0)
第二个指令是编译已由Angular编译的dom元素。第二次编译添加了第二个$watch
,解析器等,因为所有指令的链接函数都被再次调用(here's a good detailed look at $compile)为了确认这一点,您可以在console.log
内放置$watch
并且你会看到(使用第二个指令)它会为每次更改触发两次 - 因为重复$watch
(删除第二个指令并且它只触发一次 - 如预期的那样)。第二个编译步骤不仅会导致您遇到的问题,还可能导致其他问题。
如果必须重新编译Angular元素,则首先需要删除现有元素。
这是一种方法(评论中的解释):
compile: function(compileElement) {
compileElement.removeAttr('another-directive');
return function(scope, element) {
// Create an "uncompiled" element using a copy of the current element's html
newe = angular.element(element.html());
// Remember where we were
parent= element.parent();
// Deleting the current "compiled" element
element.remove();
// Add the uncompiled copy
parent.append(news);
// Compile the copy
$compile(newe)(scope);
};