等待DOM在AngularJS指令上准备就绪

时间:2014-02-26 12:47:58

标签: javascript jquery angularjs angularjs-directive intro.js

我正在为我的角度网站建立一个“导游”。

我四处寻找选项,而Intro.js似乎是最合适的选择。它有一个Angular Directive已经准备就绪,所有内容都是:Angular Intro.js

一切都按预期工作,直到我不得不向第一个(并且只是第一个)添加一个由ng-repeat绑定注入的DOM对象的步骤。我给所有ng-repeat项目提供了一个唯一的ID(通过$ index),但是Intro.js没有确认它。

我猜Intro正试图通过指定的ID找到DIV,但由于ng-repeat尚未完成,因此该名称没有DIV。

我做了一个plunker,你可以看到它正在处理静态内容,但却无法知道ng-repeat中的对象。

相关代码:

HTML:

<!-- Works -->
<div id="static">This is static content.</div>

<!-- Doesnt work -->
<div id="item{{$index}}" ng-repeat="item in items">
    {{ item.name }}
</div>

角度控制器:

  $scope.IntroOptions = {
        steps:[
        {
            element: document.querySelector('#static'),
            intro: "This is static content"
        },
        {
            /** ID "item0" belongs to the first element on the ng-repeat **/
            element: document.querySelector('#item0'),
            intro: "Doesnt work!"
        }
        ],
        showStepNumbers: false,
        exitOnOverlayClick: true,
        exitOnEsc:true,
        nextLabel: '<strong>NEXT!</strong>',
        prevLabel: '<span style="color:green">Previous</span>',
        skipLabel: 'Exit',
        doneLabel: 'Thanks'
    };

Plunker http://plnkr.co/edit/kE8P5Kq2Y5CVWEYgyBIo?p=preview

  • 假设上述原因导致无效,我该怎么办? 让指令等待DOM“准备好”?

  • 如果我的假设错了,为什么它不起作用?

4 个答案:

答案 0 :(得分:2)

.directive('onLastRepeat', function() {
    return function(scope, element, attrs) {
        if (scope.$last) setTimeout(function(){
            scope.$emit('onRepeatLast', element, attrs);
        }, 50);
};});

像这样使用这个指令:

<div id="item{{$index}}" ng-repeat="item in items" on-last-repeat>
    {{ item.name }}
</div>
在控制器中

等待完成循环并调用introjs

$scope.$on('onRepeatLast', function (eve, elem) {
//call intro
});

答案 1 :(得分:0)

我最初尝试的最无能为力的方法是包装动态内容:

<div id="dynamic">
    <div id="item{{$index}}" ng-repeat="item in items">
        {{ item.name }}
    </div>
</div>

然后,范围变量变为

$scope.IntroOptions = {
    steps:[
    {
        element: document.querySelector('#static'),
        intro: "This is static content"
    },
    {
        element: document.querySelector('#dynamic'),
        intro: "This is dynamic content"
    }
    ],
// ... cut ...

看起来您的原始代码是死锁:视图取决于依赖于视图的数据($ scope.items)(IntroOptions)

答案 2 :(得分:0)

您可以观察$ rootScope将广播的$ viewContentLoaded事件。

答案 3 :(得分:0)

我知道这已经很老了,但是如果有人发现这个答案,最好的办法是使用getter,它会在需要访问该属性时得到评估:

$scope.IntroOptions = {
    steps:[
    {
        element: document.querySelector('#static'),
        intro: "This is static content"
    },
    {
        /** ID "item0" belongs to the first element on the ng-repeat **/
        get element(){return document.querySelector('#item0')},
        intro: "Doesnt work!"
    }
    ],
    showStepNumbers: false,
    exitOnOverlayClick: true,
    exitOnEsc:true,
    nextLabel: '<strong>NEXT!</strong>',
    prevLabel: '<span style="color:green">Previous</span>',
    skipLabel: 'Exit',
    doneLabel: 'Thanks'
};