将DOM元素添加到我的指令时,如何通知我?

时间:2015-04-02 20:11:32

标签: angularjs angularjs-directive

我有一个简单的指令,它绘制了一些元素,就像在这个例子中一样。我想以编程方式设置一些样式属性,但在链接函数中,元素显然还没有。

Here's a fiddle.

我的想法是,当我调用colorSquares函数时,DOM中还没有正方形。将它包装在$ timeout中,它可以工作,但这感觉很错误。

当元素存在时,有什么方法可以通知我吗?或者,是否有一个地方可以放置访问它们的代码,保证它们存在后运行?

myApp.directive('myDirective', ['$timeout', function ($timeout) {
return {
    restrict: 'E',
    replace: false,
    link: function (scope, elem, attr) {

        scope.squares = [1,2,3,4,5];

        function colorSquares() {
            var squaresFromDOM = document.getElementsByClassName('square');
            for (var i = 0; i < squaresFromDOM.length; i++) {
                squaresFromDOM[i].style['background-color'] = '#44DD44';
            }
        }

        // this does not work, apparently because the squares are not in the DOM yet            
        colorSquares();

        // this works (usually).  It always works if I give it a delay that is long enough.           
        //$timeout(colorSquares);


    },
    template: '<div><div ng-repeat="s in squares" class="square"></div></div>'
};

}]);

3 个答案:

答案 0 :(得分:0)

您应该使用Angular而不是反对它,也就是说您应该使用数据绑定来执行您尝试执行的操作,而不是在此上下文中使用事件/通知。

http://jsfiddle.net/efdwob3v/5/

link: function (scope, elem, attr) {
    scope.squares = [1,2,3,4,5];
    scope.style = {"background-color": "red"};
},
template: '<div><div ng-repeat="s in squares" class="square" ng-style="style"></div></div>'

那说上面做的没有什么区别,只是使用了具有红色背景色的不同类,甚至只是做style="background-color: red;"

答案 1 :(得分:0)

你把答案放在你的qeustion中,&#34;如果我给它一个足够长的延迟,它总是有效的。&#34;。

所以只需要延迟足够长,在这种情况下可以通过添加onload事件来实现,因为当元素被添加到DOM时它会调用该事件。

所以不只是colorSquares();你可以使用:

window.addEventListener("load", colorSquares);

虽然这可能不是理想的解决方案,因为当其他东西触发onload事件时它也会触发。

答案 2 :(得分:0)

直接回答您的问题。要知道一个元素是否通常添加到指令或DOM中,您可以简单地在该元素上放置一个指令,因为该指令仅在其所在的元素上运行时才会运行。已经在DOM中了。

以部分代码为例:

myApp.directive('myDirective', function () {
    return {
        ...      
        //put custom directive that will notify when DOM is ready 
        template: '<div><div ng-repeat-ready ng-repeat="s in squares" class="square"></div></div>'
    };
});

这是自定义ng-repeat-ready指令:

myApp.directive('ngRepeatReady', function () {
    return {
        link: function (scope) {
            if (scope.$last) {
                //do notification stuff here
                //for example $emit an event
                scope.$emit('ng-repeat is ready');
            }
        }
    }
});

该指令将在其所在的元素已经位于DOM中并且检查该范围内的元素是否具有$last属性时运行(ng-repeat为迭代的最后一个元素设置此标志对象)这意味着ng-repeat指令已完成,您现在可以安全地操作DOM。