我可能会得到一些非常错误的概念,但是我没想到这个我想到的: http://plnkr.co/edit/Qe2IzMMMR5BJZJpwkx9e?p=preview
我要做的是定义一个附加到顶级<nav>
元素的指令,然后在其链接函数中修改包含的DOM元素(例如将css类添加到{{ 1}}等。
但是,链接函数似乎只获取原始指令模板(<li>
),而不是转换/扩展的DOM元素。
如果这是“按设计”,我应该怎么做? 如果它不能访问被转换的DOM树,那么定义一个包含“root”指令是没用的。
答案 0 :(得分:6)
ng-transclude
的默认行为。$transclude
执行任何操作,只需要小心。angular.module('app').directive ('myNav', ['$timeout', function($timeout) {
return {
replace: false,
transclude: true,
template: '<nav><ul></ul></nav>',
link: function (scope, element, attrs,ctrl,$translcude){
$transclude(scope,function(clone){
element.find('ul').html(clone)
});
var items = element.find('li'); //element.find('ng-transclude') === 1 !
window.console.log (items.length);
}
};
答案 1 :(得分:1)
(正确答案见Ilan及其他人的上述内容)
我终于让我的(简单)用例在没有转换的情况下使用旧的脏$ timeout hack:http://plnkr.co/edit/FEEDYJLK9qRt0F4DNzRr?p=preview
link: function(scope, element) {
// add to end of event queue
$timeout(function() {
var items = element.children('ul:first').children('li');
window.console.log(items.length);
}, 0);
}
我知道这是一件坏事,并不完全确定这是否会一直有效,但至少似乎适用于我的简单案例......
答案 2 :(得分:0)
我认为问题在于你在指令中有一个ng-repeat,所以“元素”在ng-repeats被解析之前无法访问子节点。解决这个问题的方法是在每个列表标签上使用您的指令。我将transclude添加到标记中,然后您可以一起从指令中删除模板。
你最终会得到类似的东西:
<li ng-repeat="item in menuItems" my-nav ng-transclude>
您的指令看起来像
angular.module('app').directive ('myNav', ['$timeout', function($timeout) {
return {
replace: false,
transclude: true,
compile: function (element, attrs, transclude){
// this will always return 0 unless you split this into two directives
// and emit or watch for the ng-repeats to complete in the parent
// directive
//var items = $(element).find('li'); //element.find('ng-transclude') === 1 !
//instead showing you how to access css for the given element
element.css( "color", "red" );
}
};
}]);
正如我在上面的评论中所提到的,您可以将指令拆分为两个指令:一个在导航级别,一个在ng-repeat上,只在重复完成时发出,并且您可以相应地应用css,因为查找将然后能够在解析子节点时找到它们。我认为这种方法是多余的,因为您要为已经应用了更改的节点设置css。我认为如下面的评论中所述,较小的指令效果更好,而且您的项目不太可能成为像范围这样的意大利面条。快乐的编码:)