指令无法访问被转换的元素?

时间:2014-01-21 18:02:12

标签: javascript angularjs

我可能会得到一些非常错误的概念,但是我没想到这个我想到的: http://plnkr.co/edit/Qe2IzMMMR5BJZJpwkx9e?p=preview

我要做的是定义一个附加到顶级<nav>元素的指令,然后在其链接函数中修改包含的DOM元素(例如将css类添加到{{ 1}}等。 但是,链接函数似乎只获取原始指令模板(<li>),而不是转换/扩展的DOM元素。

如果这是“按设计”,我应该怎么做? 如果它不能访问被转换的DOM树,那么定义一个包含“root”指令是没用的。

3 个答案:

答案 0 :(得分:6)

请阅读我关于角度转换的一些答案:

关于你的问题:

  • 首先,即使不适合您的使用案例,也没有用处。
  • 是的,这是设计的 - 但它只是ng-transclude默认行为
  • 如果情况正好相反,那么每个人都会对范围泄漏大喊大叫。
  • 您可以使用$transclude执行任何操作,只需要小心。
  • 可能有更好的解决方案,例如使用绑定创建隔离范围。

这就是你想要的(plunker):

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。我认为如下面的评论中所述,较小的指令效果更好,而且您的项目不太可能成为像范围这样的意大利面条。快乐的编码:)