I have the following template code
<template name="home">
<div class="mainBox">
<ul class="itemList">
{{#each this}}
{{> listItem}}
{{/each}}
</ul>
</div>
</template>
<template name="listItem">
<li class="item">
{{username}}
</li>
</template>
And I'd like to execute a code once ALL of the "listItem" are rendered. There are about 100 of them. I tried the following
Template.home.rendered = function() {
// is this called once all of its 'subviews' are rendered?
};
But it doesn't wait until all views are loaded.
What's the best way of knowing when all sub-view templates are loaded?
This is how I proceed :
client/views/home/home.html
<template name="home">
{{#if itemsReady}}
{{> itemsList}}
{{/if}}
</template>
<template name="itemsList">
<ul>
{{#each items}}
{{> item}}
{{/each}}
</ul>
</template>
<template name="item">
<li>{{value}}</li>
</template>
client/views/home/home.js
Template.home.helpers({
itemsReady:function(){
return Meteor.subscribe("items").ready();
}
});
Template.itemsList.helpers({
items:function(){
return Items.find();
}
});
Template.itemsList.rendered=function(){
// will output 100, once
console.log(this.$("li").length);
};
lib/collections/items.js
Items=new Mongo.Collection("items");
server/collections/items.js
insertItems=function(){
var range=_.range(100);
_.each(range,function(index){
Items.insert({value:"Item "+index});
});
};
Meteor.publish("items",function(){
return Items.find();
});
server/startup.js
Meteor.startup(function(){
Items.remove({});
if(Items.find().count()===0){
insertItems();
}
});
We specify that we want to render our list of items only when the publication is ready, so by that time data is available and the correct number of li
elements will get displayed in the list rendered callback.
Now the same using iron:router
waitOn
feature :
client/views/home/controller.js
HomeController=RouteController.extend({
template:"home",
waitOn:function(){
return Meteor.subscribe("items");
}
});
client/lib/router.js
Router.configure({
loadingTemplate:"loading"
});
Router.onBeforeAction("loading");
Router.map(function(){
this.route("home",{
path:"/",
controller:"HomeController"
});
});
client/views/loading/loading.html
<template name="loading">
<p>LOADING...</p>
</template>
Using iron:router
is probably better because it solves a common pattern elegantly : we don't need the itemsReady helper anymore, the home template will get rendered only when the WaitList
returned by waitOn will be globally ready.
One must not forget to add both a loading template and setup the default "loading" hook otherwise it won't work.
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