与已编译的Angular指令HTML交互

时间:2014-06-04 09:43:41

标签: javascript html angularjs angularjs-directive

我正在创建两个Angular指令fooContainerfoo,其中fooContainer将加载一个或多个foo元素并将其呈现在其容器中。

现在我还想将一些JavaScript事件附加到foo指令编译的fooContainer指令link函数中,因为容器应该负责某些事情,比如拖动编译了foo元素。

由于$ compile在使用templateUrl编译指令时是异步的,因此在调用$compile(html)(scope)之后HTML不能直接使用,但是如果我使用超时大约一秒钟,HTML将被呈现在我可以与它互动。

这不是最佳选择。 $ compile是否公开了一个事件或承诺,我可以用来在呈现所有HTML时收到通知?

以下是描述我的问题的Plunker http://plnkr.co/edit/coYdRqCsysV4txSFZ6DI?p=preview

4 个答案:

答案 0 :(得分:1)

按优先顺序排列的方法:

1)尽可能遵循simmi simmi的模式并使用角度(ng -...)方法。这是最可靠的。

1.5)更新:Liquinaut'属性指令'下面的方法似乎是有效的 - 我只在快速演示POC中使用它并且它工作正常。假设存在更复杂的使用情况,我宁愿选择下面的watch / jquery选项2。但请注意,$ last专门用于ng-repeat。如果您按照OP注入$ compile大块的非重复标记,那么您需要删除$ last check。并且要明确这要求您将后渲染属性添加到您正在等待渲染的元素,即(根据OP plunker)

var el = $compile('<foo><div class="hide" post-render>...

带指令:

.directive('postRender', function() {
    return function(scope, element, attrs) {
        //your code here
        element.hide();
    };
});

我已经分叉了原始的plunkr并概括了允许传递通用回调的方法:http://plnkr.co/edit/iUdbn6zAuiX7bPMwwB81?p=preview

注意:此方法仅适用于编译元素的基本活动。如果编译字符串具有角度变量插值,例如{{value}}并且您依赖于在它无法工作的回调中解决这些问题。它们目前尚未得到解决。如果使用显式链接函数重写postRender指令,也是如此。下面的选项2适用于这些情况,因为它将解决方案推至至少下一个摘要。

2)我发现即使在非常复杂的应用程序中,DOM也非常可靠(尽管应始终监控性能)。用此块替换el.find('.hide').hide();行:

scope.$watch(
  function() { return element.find('.hide').length > 0;},
  function(newVal, oldVal) {
    if (newVal) {
      //DO STUFF
      el.find('.hide').hide();
    }
  }
);

我不习惯在紧密的循环中使用它,但是在指令实例化中使用一次(假设你没有创建1000个!)这似乎是合理的 - 我用这种方法进行ng / ui-slider集成等

3)如果你正在构建更复杂的东西(以及可重用的组件),pixelbits也会采用良好的架构方法,但要注意如果你使用transclude(例如嵌套指令)创建的额外范围,它将是$$ nextSibling &#39;发出&#39;。请参阅:here

BTW:如果只想快速拖放,请参阅:http://codef0rmer.github.io/angular-dragdrop/#/

答案 1 :(得分:0)

该指令触发postRender事件:

fooContainer.directive('postRender', function() {
    return function(scope, element, attrs) {
        if (scope.$last){
            //your code here
        }
    };
});

希望有所帮助!

答案 2 :(得分:0)

http://plnkr.co/edit/f4924y6GW7rAMItqVR0L?p=preview

    .directive('fooContainer', function($compile, $timeout) {
  return {
    link: function(scope, element, attributes) {
     console.log('link called');
        var el = $compile('<foo><div class="hide" >I should always be hidden.</div><div class="hideDelay" ng-show="visiblity">I should be hidden after 1 second.</div></foo>')(scope);
       element.append(el);

         scope.visiblity=false;


    },
    restrict: 'E',
    template: '<div class="fooContainer"></div>'
  }
});

为什么不尝试使用ng-show / ng-hide

答案 3 :(得分:0)

您可以安全地将事件附加到指令的link函数中的元素,但仅限于指令的子元素。指令的父级尚未链接。

因此,在fooContainer的链接函数中,您知道foo已经被编译和链接,并且附加事件是安全的。

如果fooContainer链接后需要通知foo,您可以使用某种形式的指令间通信。即$ scope。$ emit。如果要将事件附加到foo,还可以在fooContainer的链接函数中使用jquery选择器。

根据Angular文档:

templateUrl

Same as template but the template is loaded from the specified URL. 
Because the template loading is asynchronous the compilation/linking
is suspended until the template is loaded

这意味着您的模板已在链接功能执行时加载。不需要承诺对象。