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?
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.
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">
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.
.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
});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With