次のように述べて、問題を正しく特定しました。
テンプレートの #each-part が完了する前、またはデータが到着する前に、 Template.featuredCarousel.rendered 内の関数が呼び出されるようです。
テンプレートのrendered
コールバックは、テンプレート インスタンスが最初に DOM に挿入されたときに 1 回だけ呼び出されるため、データの準備ができていない (サーバーから取得された) 場合でも、#each ブロックは HTML 要素を生成せず、カルーセルをインスタンス化するときに呼び出されます。空に見えます。
できることは、rendered
コールバックが発生する前にデータの準備ができていることを確認することです。どうやらこのソリューションをうまくセットアップしようとしたようですが、デフォルトの読み込みフックをそのように追加しましたか?
Router.onBeforeAction("loading");
さらに良い解決策は、レンダリングされたコールバックでデータベースの変更をリッスンし、アイテムが最初にフェッチされたときにそれに応じてカルーセルを再初期化し、動的に追加および/または削除することです。
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 the #each with our cursor
featuredPosts:featuredPosts
});
Template.carousel.rendered=function(){
var options={...};
// first initialization
this.$(".owl-carousel").owlCarousel(options);
this.autorun(_.bind(function(){
// this is how we "listen" for databases change : we setup a reactive computation
// and inside we reference a cursor (query) from the database and register
// dependencies on it by calling cursor.forEach, so whenever the documents found
// by the cursor are modified on the server, the computation is rerun with
// updated content, note that we use the SAME CURSOR that we fed our #each with
var posts=featuredPosts();
// forEach registers dependencies on the cursor content exactly like #each does
posts.forEach(function(post){...});
// finally we need to reinit the carousel so it take into account our newly added
// HTML elements as carousel items, but we can only do that AFTER the #each block
// has finished inserting in the DOM, this is why we have to use Deps.afterFlush
// the #each block itself setup another computation and Deps.afterFlush makes sure
// this computation is done before executing our callback
Tracker.afterFlush(_.bind(function(){
this.$(".owl-carousel").data("owlCarousel").reinit(options);
},this));
},this));
};
私は owl-carousel に詳しくないので、reinit が適切に動作するかどうかはわかりません (ドキュメントをすぐに確認したところ、問題ないようです)。
再初期化メソッドが利用できない同様の JS プラグイン (ブートストラップ カルーセルなど) の場合、最初にプラグインがインスタンス化されているかどうかを確認してから破棄し、次のように再作成できます。
var carousel=this.$(".carousel").data("bs.carousel");
if(carousel){
// bootstrap carousel has no destroy either so we simulate it by pausing it
// and resetting the data attribute to null (it's a bit messy)
this.$(".carousel").carousel("pause");
this.$(".carousel").data("bs.carousel",null);
}
// initialize normally because previous instance was killed
this.$(".carousel").carousel({...});