指令中缺少子元素

时间:2013-12-19 01:34:47

标签: jquery angularjs angularjs-directive

我有一个定义的指令:


$(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。 / p>

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

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

2 个答案:

答案 0 :(得分: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和Angular自己Misko Hevery的评论:

  

这是一个非常复杂的问题。问题在于   数据绑定没有明确的更新周期的开始/结束,它是   继续。我相信这不是你要找的答案,但是   角度与其他框架不同,所以它的生活方式与众不同   规则。

     

你怎么能想到这会起作用?什么样的,何时应该   你会收到这些通知。

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

  

我只是对$ timeout下方感到好奇

我认为这种做法令人鼓舞,没有人发布下行。

答案 1 :(得分:1)

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

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