首页 文章

指令中缺少子元素

提问于
浏览
1

我有一个定义的指令:

$(function () {
    angular.module(['myApp']).directive('rootSlider', function () {
        return {
            restrict: 'E',
            template: '<ul><li ng-repeat="item in items"><img ng-src="{{item.url}}" /></li></ul>',           
            scope: {
                items: '='
            },
            replace: true,
            compile: function ($templateElement, $templateAttributes) {
                return function ($scope, $element, $attrs) {

                    var $scope.items.length //expect 2, get 2
                    var numChildren $element.children().length //expect 2, get 0
                };
            }
        };
    });
});

虽然 $scope.items 属性有2个项目,并且在最终呈现的DOM中有两个 <li> 元素,但在链接函数 $element 中还没有子元素 .

在角度生命周期的什么时候我可以得到完全渲染的元素(我的意图是在这里使用jQuery滑块插件) .

标记是

<root-slider items="ModelPropertyWithTwoItems"></root-slider>

更新:

我能够通过$ watchCollection和$ evalAsync的组合使其正常工作 .

$(function () {
    angular.module(['myApp']).directive('rootSlider', ['$timeout', function ($timeout) {
        return {
            restrict: 'E',
            template: '<ul class="bxslider"><li ng-repeat="item in items"><img ng-src="{{item.url}}" /></li></ul>',
            scope: {
                items: '='
            },
            compile: function ($templateElement, $templateAttributes) {
                return function ($scope, $element, $attrs) {
                    $scope.$watchCollection('items', function (newCollection, oldCollection) {
                        if ($scope.slider) {
                            $scope.$evalAsync(function () {
                                $scope.slider.reloadSlider();
                            });
                        }
                        else {

                            $scope.$evalAsync(function () {
                                $scope.slider = $element.find('.bxslider').bxSlider();
                            });
                        }

                    });

                };
            }
        };
    } ]);
});

监视集合在指令初始化时触发一次(因为它是一个集合,你无法比较newValue和oldValue,所以我最终将滑块对象添加到为指令实例创建的$ scope中 .

我使用$ evalAsync来推迟jQuery代码的执行(到目前为止)证明它可以避免在所有浏览器上闪烁(它似乎在$ timeout(function(){},0)之前运行 .

只需返回一个链接函数(而不是编译函数,结果是不必要的),可以简化上面的解决方案 .

2 回答

  • 2

    等待DOM在Angular中完成渲染的常用方法是使用 $timeout . 这是各种选项的explanationhere's another look at this .

    所以这应该为你解决这个问题 . 在您的指令中包含 $timeout

    angular.module(['myApp']).directive('rootSlider', function ($timeout) {
    

    然后包装你的

    $timeout(function() {
         var numChildren $element.children().length;
    },0);
    

    在他关闭这个问题之前,有一个request for a more official feature supporting this和这里有's Angular'的评论:

    这是一个非常复杂的问题 . 问题是,对于数据绑定,更新周期没有明确的开始/结束,它仍在继续 . 我确信这不是您正在寻找的答案,但角度与其他框架不同,因此它遵循不同的规则 . 你怎么想象这会起作用?什么样的,什么时候应该收到这些通知 .

    到目前为止,似乎没有人对3emad最后发布的问题做出回应:

    我只是对$ timeout表示好奇

    我认为这种方法令人鼓舞,没有人发布下行方面 .

  • 1

    您可能希望使用$watch来赶上模型的更改 .

    $scope.$watch('items', function(newValue) {
        // logic about items here...
    }, true); // pass true since it should be an array
    

相关问题