Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Wait for DOM to be ready on an AngularJS directive

I'm building a "tour guide" for my angular powered website.

I looked around for options and Intro.js seemed like the best fit. It had an Angular Directive already ready and everything: Angular Intro.js.

Everything worked as expected, until I had to add a step to first (and only the first) a DOM object that is being injected by a ng-repeat binding. I gave all ng-repeat items a unique ID (via $index) but Intro.js just fails to acknowledge it.

I'm guessing Intro is trying to find the DIV by the ID specified, but since the ng-repeat isn't complete yet, there's no DIV by that name.

I made a plunker where you can see that it' working on static content but fails to aknowledge the objects inside the ng-repeat.

Relevant code:

HTML:

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

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

Angular Controller:

  $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

  • Assuming the reason above is the reason this isn't working, how do I make the directive wait for the DOM to be "ready"?

  • If my assumption is wrong, why isn't it working then?

like image 596
pedropeixoto Avatar asked Feb 26 '14 12:02

pedropeixoto


People also ask

What is restrict option in directive?

Note: When you create a directive, it is restricted to attribute and elements only by default. In order to create directives that are triggered by class name, you need to use the restrict option. The restrict option is typically set to: 'A' - only matches attribute name. 'E' - only matches element name.

What is attrs in AngularJS?

Using attrs you are able to access the attributes defined in your html tag like <fm-rating ng-model="$parent.restaurant.price" symbol="$" readonly="true">

What is jqLite?

jqLite is a tiny, API-compatible subset of jQuery that allows AngularJS to manipulate the DOM in a cross-browser compatible way. jqLite implements only the most commonly needed functionality with the goal of having a very small footprint. To use jQuery , simply ensure it is loaded before the angular.


1 Answers

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

Use this directive like this :

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

in your controller wait for finish the loop and call introjs

$scope.$on('onRepeatLast', function (eve, elem) {
//call intro
});
like image 62
mostafa shaheydari Avatar answered Oct 04 '22 13:10

mostafa shaheydari