Reputation: 966
Before 0.8.0, the following code works perfectly.
<template name="carousel">
<!--Here I used the carousel of Bootstrap-->
<div id="myCarousel" class="carousel">
<ol class="carousel-indicators">
{{#each counter}}
<li data-target="#myCarousel" data-slide-to="{{this}}"></li>
{{/each}}
</ol>
<div class="carousel-inner">
{{#each carousels}}
<div class="item"><a href="{{link}}"><img src="{{src}}" ></a></div>
{{/each}}
</div>
<a class="carousel-control left" href="#myCarousel" data-slide="prev">‹</a>
<a class="carousel-control right" href="#myCarousel" data-slide="next">›</a>
</div>
</template>
Template.carousel.helpers({
carousels: function() {
return Carousels.find();
},
counter: function() {
return _.range(0, Carousels.find().count());
}
});
Template.carousel.rendered = function() {
Meteor.defer(function() {
$('#myCarousel .carousel-indicators li:first').addClass('active');
$('#myCarousel .item:first').addClass('active');
});
}
But after updating to 0.8.0, adding 'active' class doesn't work any more. Using Meteor.setTimeout instead of Meteor.defer, I finally find that it works only when the delay is long enough (sometimes longer than 150ms).
Template.carousel.rendered = function() {
Meteor.setTimeout(function() {
$('#myCarousel .carousel-indicators li:first').addClass('active');
$('#myCarousel .item:first').addClass('active');
}, 150);
}
Why does this happen, and is there any better solution?
[Updated] Now I use a simple isFirst helper to realize it. I think this is a better solution.
{{#each carousels}}
<div class="item {{isFirst _id}}"><a href="{{link}}"><img src="{{src}}" ></a></div>
{{/each}}
Template.carousel.isFirst = function(id) {
return Carousels.find().fetch()[0]._id == id ? 'active' : '';
}
As for the counter, I just make "counter" begin from 1, and the HTML is as follows:
<ol class="carousel-indicators">
<li class="active" data-target="#myCarousel" data-slide-to="0"></li>
{{#each counter}}
<li data-target="#myCarousel" data-slide-to="{{this}}"></li>
{{/each}}
</ol>
Upvotes: 3
Views: 422
Reputation: 4716
Template.carousel.rendered only runs once in Blaze (Meteor's new rendering engine), but it used to run multiple times in Spark (previous versions). This old behaviour worked because it ran before and after your {{#each}} block was rendered.
The problem here is that Template.carousel.rendered runs before your {{#each}} block is rendered, so those items don't exist yet.
The recommended pattern is to put the contents of your {{#each}} in a separate template and tap into the rendered event of that template.
By the way, Meteor.defer is no longer required.
Upvotes: 2