AngularJS:当 parent 具有 ngIf 指令时,为什么我不能向 grandparent 元素添加属性
AngularJS: Why can't I add an attribute to grandparent element when parent has ngIf directive
我正在使用 vanilla AngularJS v1.4.5(没有 jQuery),并希望我的自定义指令在编译时向其 grandparent 元素添加一个属性。
在compile函数中,我可以使用element
的parent()
方法两次得到grandparent元素,attr()
方法添加我的属性。但是,如果 parent 元素具有 ngIf 指令,则 grandparent 元素不会获得该属性。
angular.module('myApp', [])
.directive('foo', fooDirective)
;
function fooDirective() {
return {
compile : compile,
priority: 601 // ngIf is 600
};
function compile(element, attrs) {
var parent, grandparent;
parent = element.parent();
grandparent = parent.parent();
parent.attr('foo', 'bar');
grandparent.attr('foo', 'bar');
}
}
这是我所知道的:
- 如果
ngIf
未在 parent 元素上使用,该属性将添加到 grandparent。
- 问题应该与
scope
无关,因为这是在编译阶段发生的,在作用域链接到任何元素之前。
- 我的编译函数应该运行在
ngIf
之前,它的优先级是600
(和doesn't have a compile function)。
ngIf
完全删除并重新创建 DOM 中的元素(及其 child 元素),但这不应影响 grandparent 元素或更改是属性。
如果 parent 元素具有 ngIf
指令,谁能向我解释为什么我不能向指令的 grandparent 元素添加属性?
我还不完全确定为什么会发生这种情况,但是您是否有任何特殊原因为什么要使用编译来执行此操作?我调整了你的指令以使用 link,它似乎工作得很好。
(function () {
'use strict';
angular.module('myApp', [])
.directive('foo', fooDirective)
;
function fooDirective() {
return {
link : link,
priority: 601 // ngIf is 600
};
function link($scope, element, attrs) {
var parent, grandparent;
parent = element.parent();
grandparent = parent.parent();
parent.attr('foo', 'bar');
grandparent.attr('foo', 'bar');
}
}
})();
编辑:
就像@NewDev 说的那样,您通常应该在 link 阶段而不是在编译期间进行 DOM 操作。
所以,重申一下,问题是,为什么给出以下内容:
<grand-parent>
<parent ng-if="condition">
<foo></foo>
</parent>
</grand-parent>
尝试从 foo
的编译中检索 var grandparent = tElement.parent().parent()
时,grandparent
未引用 <grand-parent>
元素。
答案是因为ngIf
引起的包含,即使condition === true
.
嵌入是将内容(或元素 + 内容,取决于嵌入的类型)从 DOM 中抽出、编译,然后作为克隆提供给包含函数,它本身可用作 link
函数的第 5 个参数:
link: function(scope, element, attrs, ctrls, transcludeFn){
transcludeFn(scope, function cloneAttachFn(clonedContent){
// clonedContent is the subtree that was transcluded, compiled and cloned
element.append(clonedContent);
});
}
因此,编译过程从 <grand-parent>
开始,然后转到 <parent>
,在那里它看到一个指令 - ngIf
。因为 ngIf
有 transclude: "element"
,它从 DOM 中抽取 <parent><foo></foo></parent>
,然后编译它。因此,编译继续在 <parent>
上编译其他优先级较低的指令(如果可用),然后编译 foo
指令。
此时,<foo>
不在 <grand-parent>
之下,tElement.parent().parent()
产生 []
。
我正在使用 vanilla AngularJS v1.4.5(没有 jQuery),并希望我的自定义指令在编译时向其 grandparent 元素添加一个属性。
在compile函数中,我可以使用element
的parent()
方法两次得到grandparent元素,attr()
方法添加我的属性。但是,如果 parent 元素具有 ngIf 指令,则 grandparent 元素不会获得该属性。
angular.module('myApp', [])
.directive('foo', fooDirective)
;
function fooDirective() {
return {
compile : compile,
priority: 601 // ngIf is 600
};
function compile(element, attrs) {
var parent, grandparent;
parent = element.parent();
grandparent = parent.parent();
parent.attr('foo', 'bar');
grandparent.attr('foo', 'bar');
}
}
这是我所知道的:
- 如果
ngIf
未在 parent 元素上使用,该属性将添加到 grandparent。 - 问题应该与
scope
无关,因为这是在编译阶段发生的,在作用域链接到任何元素之前。 - 我的编译函数应该运行在
ngIf
之前,它的优先级是600
(和doesn't have a compile function)。 ngIf
完全删除并重新创建 DOM 中的元素(及其 child 元素),但这不应影响 grandparent 元素或更改是属性。
如果 parent 元素具有 ngIf
指令,谁能向我解释为什么我不能向指令的 grandparent 元素添加属性?
我还不完全确定为什么会发生这种情况,但是您是否有任何特殊原因为什么要使用编译来执行此操作?我调整了你的指令以使用 link,它似乎工作得很好。
(function () {
'use strict';
angular.module('myApp', [])
.directive('foo', fooDirective)
;
function fooDirective() {
return {
link : link,
priority: 601 // ngIf is 600
};
function link($scope, element, attrs) {
var parent, grandparent;
parent = element.parent();
grandparent = parent.parent();
parent.attr('foo', 'bar');
grandparent.attr('foo', 'bar');
}
}
})();
编辑: 就像@NewDev 说的那样,您通常应该在 link 阶段而不是在编译期间进行 DOM 操作。
所以,重申一下,问题是,为什么给出以下内容:
<grand-parent>
<parent ng-if="condition">
<foo></foo>
</parent>
</grand-parent>
尝试从 foo
的编译中检索 var grandparent = tElement.parent().parent()
时,grandparent
未引用 <grand-parent>
元素。
答案是因为ngIf
引起的包含,即使condition === true
.
嵌入是将内容(或元素 + 内容,取决于嵌入的类型)从 DOM 中抽出、编译,然后作为克隆提供给包含函数,它本身可用作 link
函数的第 5 个参数:
link: function(scope, element, attrs, ctrls, transcludeFn){
transcludeFn(scope, function cloneAttachFn(clonedContent){
// clonedContent is the subtree that was transcluded, compiled and cloned
element.append(clonedContent);
});
}
因此,编译过程从 <grand-parent>
开始,然后转到 <parent>
,在那里它看到一个指令 - ngIf
。因为 ngIf
有 transclude: "element"
,它从 DOM 中抽取 <parent><foo></foo></parent>
,然后编译它。因此,编译继续在 <parent>
上编译其他优先级较低的指令(如果可用),然后编译 foo
指令。
此时,<foo>
不在 <grand-parent>
之下,tElement.parent().parent()
产生 []
。