javascript - AngularJS:为什么这个委托(delegate)的 ng-repeat 在嵌入中不起作用?

标签 javascript angularjs dom

好吧,这可能看起来有些深奥,但我正在尝试使用我编写的指令解决特定问题:https://github.com/michaelbromley/angularUtils/issues/37

这是正在发生的事情的简化版本。

这有效:

我有一个指令,通过动态添加 ng-repeat 委托(delegate)给 ng-repeat在编译阶段为元素添加属性,然后编译该元素:

myApp.directive('repeatDelegator', function($compile, $timeout) {
  return {
    compile: function(element, attrs){
        attrs.$set('ngRepeat', attrs.repeatDelegator); //Add ng-repeat to the dom
        element.removeAttr('repeat-delegator'); // remove the repeat-delegator to prevent infinite recursion of compilation

        var compiled =  $compile(element, null);
        return function(scope, element, attrs){
            compiled(scope);
        };
      }
   }
});

指令是这样调用的:

<ul>
    <li repeat-delegator="item in items">{{item}}</li>
</ul>

这工作正常 - 请参阅此处的第一个示例:http://plnkr.co/edit/oWd3rGAulsxoeSqffxMU?p=preview

但是,当 repeat-delegator放在任何其他使用包含的指令中,它不起作用。

这行不通。为什么?

这是一个基本指令,除了导致嵌入之外什么都不做:

myApp.directive('transcluder', function() {
    return {
        restrict: 'AE',
        transclude: true,
        scope: {},
        template: '<div ng-transclude></div>'
      };
});

所以当我们调用 repeat-delegator在此嵌入中的指令,它失败并且没有显示任何内容:

<transcluder>
    <ul>
        <li repeat-delegator="meal in meals">{{meal}}</li>
    </ul>
</transcluder>

第二个示例说明了这一点:http://plnkr.co/edit/oWd3rGAulsxoeSqffxMU?p=preview

目前我所知道的:

我花了几个小时逐步查看 Angular.js 源代码,因为它执行时试图找出它在嵌入内失败的原因,但我无法深入了解它。

在损坏的(嵌入的)版本中,当我看到正在编译的 ngRepeat 时,$scope 似乎是正确的(它是主 Controller $scope 的子 $scope,因为嵌入导致新的子 $scope被创建)。您可以在控制台中写入“scope.items”并查看项目列表。

我猜是这样的事情正在发生:

  • transcluder指令最先被编译,因为它在DOM树中的位置更高,所以最先遇到。
  • 嵌入导致指令的子节点从 DOM 中移除并克隆到 $template 中var,用于稍后插入回 DOM。
  • 也许这会导致 ng-repeat针对 <li>..</li>克隆 进行编译节点,实际上永远不会附加回 DOM?

虽然我不确定。这是一个非常棘手的问题,我们将不胜感激任何帮助!

最佳答案

好吧,在花了一天时间在开发工具中破解 Angular.js 源代码之后,我弄清楚了这里出了什么问题,我上面的猜测基本上是正确的。

问题在于 repeat-delegator 指令会针对分离的克隆进行编译,因此有效地 ng-repeated 元素将附加到丢失的 DOM 片段,而该片段永远不会附加回页面正文。

解决方案相当简单:将 repeat-delegator 委托(delegate)的 ng-repeat 的编译移动到链接函数中(而不是在编译阶段,它最初所在的位置)。

这样做意味着当 ng-repeat 被编译时,它是针对正确的 DOM 节点完成的,该节点现在安全地附加到 transcluded 指令下方的 DOM。

myApp.directive('repeatDelegator', function($compile, $timeout) {
    return {
      compile: function(element, attrs){
          attrs.$set('ngRepeat', attrs.repeatDelegator); //Add ng-repeat to the dom
          element.removeAttr(attrs.$attr.repeatDelegator); // remove the repeat-delegator to prevent infinite recursion of compilation

          return function(scope, element, attrs){
              var compiled =  $compile(element);
              compiled(scope);
          };
      }
   }
});

关于javascript - AngularJS:为什么这个委托(delegate)的 ng-repeat 在嵌入中不起作用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25424491/

相关文章:

没有jquery的javascript可折叠表格

javascript - 两个数组的智能合并(3-way-kindof)

javascript - JSON.parse 字符串中带有特殊字符的意外字符?

html - AngularStrap Accordion 菜单,试图上下切换图标箭头

javascript - Angular 全栈 + CORS : XMLHttpRequest cannot load

javascript - 如何使用 CSS 隐藏 <select> 菜单中的 <option>?

java - 解析 XML,调用 doc.getDocumentElement().getNodeName() 并得到 "h1"的错误输出?

javascript - Cookie 一小时后就会过期吗?

javascript - 如何在 Angular 中掌握这个条件 promise ?

javascript - 延迟 javascript 执行直到 DOM 更改完成