2014-02-26 3 views
5

Я создаю «путеводитель» для моего сайта с угловым питанием.Подождите, пока DOM будет готов по директиве AngularJS

Я искал варианты и Intro.js казался лучшим. У него была угловая директива, уже готовая и все: Angular Intro.js.

Все работало, как ожидалось, до тех пор, пока я не должен был добавить шаг сначала (и только первый) объект DOM, который вводится привязкой ng-repeat. Я дал всем элементам ng-repeat уникальный идентификатор (через $ index), но Intro.js просто не смог его подтвердить.

Я предполагаю, что Intro пытается найти DIV по указанному ID, но поскольку ng-repeat еще не завершен, DIV этим именем не существует.

Я сделал плункер, где вы можете видеть, что он работает на статическом контенте, но не может познать объекты внутри 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 будет «готова»?

  • Если мое предположение неверно, почему он не работает тогда?

+1

Всегда отправляйте соответствующий код ** в ** вопрос, не просто ссылку. Ссылки гниют. –

+0

сделаю, спасибо. – pedropeixoto

+0

'document.querySelector' - это грязный код для контроллера. Создайте директиву для управления DOM. – asgoth

ответ

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)

+0

Это просто выделит DIV, окружающий все предметы. Я хочу только выделить первый. Я понимаю, что я не прояснил этот вопрос, сожалею об этом. Я отредактировал его, чтобы уточнить этот момент. – pedropeixoto

+0

Хорошо, теперь я понял. Я еще больше испорчу код. – Alex

0

Вы можете наблюдать за событием $ viewContentLoaded, которое будет транслировать $ rootScope.

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' 
}; 
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 
}); 
Смежные вопросы