指令如何等待元素的动态插值属性被处理?

时间:2014-07-29 22:43:21

标签: javascript html css angularjs angularjs-directive

我有一个名为“connection”的指令,它给出了div的id之外的两个其他div之间的连接线。 id通过一些范围数据间接传递。

我的“连接”指令需要获取命名DOM元素的边界矩形,以便它可以在它们之间用适当的坐标绘制连接线。

在我的指令的link函数中,为这些id调用getElementById()会返回undefined。这是因为在DOM中,当运行我的连接指令的链接函数时,这些元素的id仍然是id="intf-{{intf.id}}“的形式(即,它们尚未被插值)。

有问题的div是使用ng-repeat生成的,并且动态分配了它们。

主要问题

如何使我的指令有效地等待元素id进行插值,然后立即通知我的指令,以便它可以更新其模板和/或范围数据?

或者,我可以强制插值立即发生,以便getElementById()可以工作,然后继续我的链接功能吗?

$观察?

我已经看到你可以使用attrs.$observe()来了解你自己的attr何时更新了,但我看不出如何使用任意元素的attrs来做到这一点。实际上,在插入名称之前,我甚至无法获取元素,因为这是我能识别它的唯一方法。

不完整的解决方案

作为一个不完整的解决方案,以前开发此代码的开发人员添加了类似的内容:

link: function( scope, element, attrs ) {
   var deferUntilElementsExist = function( newVal, oldVal, cb ){
       var sourceElement = document.getElementById(scope.connection.source().id);
       var targetElement = document.getElementById(scope.connection.target().id);
      if( !sourceElement || !targetElement ) {
         $timeout( function(){ deferUntilElementsExist( newVal, oldVal, cb ); }, 0 );
         return;
      }

       updatePath();
       if (cb) {
           cb( newVal, oldVal );
       }
   };

这种工作,但线条看起来非常缓慢,就像每秒5个左右,即使有数百个,就好像它每个更新周期处理一行或类似的东西。

感谢。

1 个答案:

答案 0 :(得分:1)

来自@pixelbits的评论让我朝着正确的方向前进。将第三个参数添加到$ timeout()设置为false,这会在每次调用后阻止$ apply(),使得" Incomplete Solution"工作得快得多。

link: function( scope, element, attrs ) {
   var deferUntilElementsExist = function( newVal, oldVal, cb ){
       var sourceElement = document.getElementById(scope.connection.source().id);
       var targetElement = document.getElementById(scope.connection.target().id);
      if( !sourceElement || !targetElement ) {
         $timeout( function(){ deferUntilElementsExist( newVal, oldVal, cb ); },
                   0, false );  // Added third parameter here set to false
         return;
      }

       updatePath();
       if (cb) {
           cb( newVal, oldVal );
       }
   };