AngularJS指令在元素完全加载之前运行

时间:2015-08-18 13:38:36

标签: angularjs angularjs-directive

我有一个指令附加到模板中动态生成的<table>元素。该指令在link函数内操作该表的DOM。问题是指令在表呈现之前运行(通过评估ng-repeat指令) - 表是空的。

问题

如何确保在完全呈现表后运行该指令?

<table directive-name>
    <tr ng-repeat="...">
        <td ng-repeat="..."></td>
    </tr>
</table>


module.directive("directiveName", function() {
    return {
        scope: "A",
        link: function(scope, element, attributes) {
            /* I need to be sure that the table is already fully
               rendered when this code runs */
        }
    };
});

3 个答案:

答案 0 :(得分:6)

从一般意义上说,你不能完全确定&#34;只需在<table>元素上有一个指令。

但在某些情况下你可以肯定。在您的情况下,如果内部内容为ng-repeat - ed,那么如果ngRepeat工作的项目数组已准备就绪,那么实际DOM元素将在摘要周期结束时准备就绪。您可以在$timeout之后以0延迟捕获它:

link: function(scope, element){
  $timeout(function(){
    console.log(element.find("tr").length); // will be > 0
  })
}

但是,从一般意义上讲,您无法确定捕获内容。如果ngRepeat ed数组还没有呢?或者如果有ng-include而该怎么办?

<table directive-name ng-include="'templates/tr.html'">
</table>

或者,如果有一个与ngRepeat不同的自定义指令呢?

但是如果您完全控制了内容,一种可能的方法就是将一些辅助指令作为最内层/最后一个元素包含在内,并在它链接时让它与其父directiveName联系:

<table directive-name>
    <tr ng-repeat="...">
        <td ng-repeat="...">
          <directive-name-helper ng-if="$last">
        </td>
    </tr>
</table>
.directive("directiveNameHelper", function(){
  return {
    require: "?^directiveName",
    link: function(scope, element, attrs, ctrl){
      if (!ctrl) return;

      ctrl.notifyDone();
    }
  }
})

答案 1 :(得分:5)

尝试在链接函数的$timeout中包装,因为它将在呈现DOM后执行。

$timeout(function () {
    //do your stuff here as the DOM has finished rendering already
});

不要忘记在你的指令中注入$timeout

.directive("directiveName", function($timeout) {

有很多替代方案,但我认为这个更清晰,因为$ timeout在渲染引擎完成其工作后执行。

答案 2 :(得分:0)

干净的方法是使用像lodash's _.defer method这样的东西。

当当前调用堆栈已清除且一切准备就绪时,您可以在链接中使用_.defer(your_func, your_func_arg1, your_func_arg2, ...)调用它来执行该方法。

这样,您就不必自己估算$timeout