我对Angular bootstraps的方式有疑问。考虑这个指令:
app.directive('finder', function () {
return {
restrict: 'E',
replace: true,
template:'<div><input type="text" data-ng-model="my-input" style="width:80%;" /></div>',
compile: function (element, attributes) {
if (attributes.hasOwnProperty('required')) {
element.removeAttr('required');
element.find(':input').attr('required', true);
element.removeClass("ng-invalid ng-invalid-required");
}
return {
post: function postLink(scope, iElement, attributes) {
// Do some other stuff
}
}
}
}
})
我使用此指令如下:
<div>
<finder required></finder>
</div>
一些CSS:
.ng-invalid-required {
background: yellow;
}
正如您在指令中看到的那样,在编译阶段,我从元素中删除required
属性,并将属性添加到input
元素。结果是你应该期望的:主要元素不再具有该属性,但输入字段确实如此。
现在很奇怪&#39; part:输出显示div也有黄色背景。事实证明,主要元素(div)具有ng-invalid-required
类!这很奇怪,因为我在编译阶段删除了required
属性......
这怎么可能?
显然,Angular会扫描整个DOM以获取指令,并使用所属元素收集指令。扫描完成后,Angular将编译所有指令。有一次,它将编译我的finder
指令。该指令删除所需的属性并将其添加到我的输入字段。稍后它会编译所需的属性。因为&#39;原始元素&#39;在收集的列表中,它将ng-invalid-required
类添加到链接元素(div)。
这是对的吗?或者是否有这种行为的另一种解释?
编辑(感谢Nikos Paraskevopoulos在评论中提出的建议) 有趣的是:当我将其添加到指令中时: priority: 1000,
terminal: true
它像我期望的那样工作。但是当我离开其中一个属性时,它再也不起作用了。有人可以向我解释为什么这有效吗?
答案 0 :(得分:1)
“required”是在你的元素之前编译的,所以我认为即使你删除了必需的属性,它也已被标记为必需,angularjs会添加ng-invalid class。
尝试将指令的优先级更改为1000,因此它将在required指令之前编译,因此您可以删除所需的属性:
app.directive('finder', function () {
return {
priority: 100,
restrict: 'E',
...
};
});
答案 1 :(得分:1)
(从评论转到答案+解释)
尝试在指令定义中同时指定priority
(以使指令在requiredDirective
之前运行)和terminal: true
。
<强>解释强>
原始问题的原因是requiredDirective
在元素上执行。显然,正如您所指出的,Angular会扫描整个DOM以获取指令并收集指令并执行它们。澄清一下:首先收集它们,然后执行它们。
这意味着,尽管您的requiredDirective
功能删除了compile()
属性,required
仍会执行,因为Angular已经收集了&#34;&#34;指令。
terminal: true
属性:
如果设置为true,则当前优先级将是将执行的最后一组指令
这意味着如果您将某个值设置为优先级,以便您的指令在 requiredDirective
之前执行,则后者将根本不执行!显然,Angular 在遇到terminal: true
的指令时会停止指令集合。