Meteor: Call function after template is rendered with data -
i have number of posts want display inside of carousel. carousel, use owlcarousel .
<div class="owl-carousel" id="featured-carousel"> {{#each featuredposts}} <div> <h2> {{posttitle}} </h2> </div> {{/each}} </div>
i call carousel so:
template.featuredcarousel.rendered = function(){ $('#featured-carousel').owlcarousel({ loop:true, autoplay:true, autoplaytimeout:3000, items:1, smartspeed:1080, padding:80 }); this.rendered = true; };
the result owl thinks have 1 item display in carousel multiple divs. apparently happens function inside template.featuredcarousel.rendered called before #each-part of template completed or before data has arrived.
how can make function instantiating carousel called after template rendered including data?
thank help.
p.s.: use iron-router routing so:
router.map(function(){ this.route('home', { path: '/', waiton: function(){ return meteor.subscribe('featured'); }, data: function(){ return {featuredposts: featured.find({})}; } }); });
p.p.s.: have tried using loading template doesn't either.
you have identified problem correctly stating :
what apparently happens function inside template.featuredcarousel.rendered called before #each-part of template completed or before data has arrived.
the rendered
callback of template called once when template instance first inserted in dom, if data not ready (fetched server) yet #each block won't generate html elements , when instantiate carousel appear empty.
what can make sure data ready before rendered
callback fires. apparently you've tried setup solution no luck, sure added default loading hook ?
router.onbeforeaction("loading");
an better solution listen database changes in rendered callback , reinitialize carousel accordingly when items first fetched, , dynamically added and/or removed.
html
<template name="carousel"> <div class="owl-carousel"> {{#each featuredposts}} {{! item declaration}} {{/each}} </div> </template>
js
function featuredposts(){ return featured.find(); } template.carousel.helpers({ // feed #each our cursor featuredposts:featuredposts }); template.carousel.rendered=function(){ var options={...}; // first initialization this.$(".owl-carousel").owlcarousel(options); this.autorun(_.bind(function(){ // how "listen" databases change : setup reactive computation // , inside reference cursor (query) database , register // dependencies on calling cursor.foreach, whenever documents found // cursor modified on server, computation rerun // updated content, note use same cursor fed our #each var posts=featuredposts(); // foreach registers dependencies on cursor content #each posts.foreach(function(post){...}); // need reinit carousel take account our newly added // html elements carousel items, can after #each block // has finished inserting in dom, why have use deps.afterflush // #each block setup computation , deps.afterflush makes sure // computation done before executing our callback tracker.afterflush(_.bind(function(){ this.$(".owl-carousel").data("owlcarousel").reinit(options); },this)); },this)); };
i'm not familiar owl-carousel i'm not sure if reinit act (i've checked documentation , seems ok though).
for similar js plugins reinit method not available (bootstrap carousel example), can first check if plugin has been instantiated destroy , recreate :
var carousel=this.$(".carousel").data("bs.carousel"); if(carousel){ // bootstrap carousel has no destroy either simulate pausing // , resetting data attribute null (it's bit messy) this.$(".carousel").carousel("pause"); this.$(".carousel").data("bs.carousel",null); } // initialize because previous instance killed this.$(".carousel").carousel({...});
Comments
Post a Comment