2015-09-08 10 views
6

#eachが終了した後にコールバックに問題があります。#eachの実行後にコールバックを実行するにはどうすればよいですか?

<template name="content"> 
{{#if Template.subscriptionsReady}} 
    {{#each currentData}} 
     <div data-cid="{{this._id}}"></div> 
    {{/each}} 
{{else}} 
    Loading... 
{{/if}} 
</template> 

まず私は{{#each}}と私のコレクションを反復処理し、divを追加し、これが利用可能な場合、サブスクリプションを待つ:私は、「コンテンツ」という名前のテンプレートを持っています。私が必要とするのは、for-eachループが完了したときのコールバック(つまり、DOM対応)です。

Template.content.onRendered() 

- > Iはまた、{{各}}後の画像を追加しようと、このようにそのonloadに機能を発射初期

にトリガ - >仕事をした

<img style="height:0;width:0" src="*mysource*" onload="callback()"> 

は時には信頼できるものではない

このコールバックを取得する方法はありますか?私はこのテンプレートの構造を変えることを恐れない。それが解決策をもたらすならば。

+0

これは重複しているかどうかわかりませんが、確かに[この質問]と同じ感じです(https://stackoverflow.com/questions/30140232/meteor-with-iron-router-cant-getスラック・カルーセル作業)。 –

答えて

1

私も同様の問題がありました。多くの検索の結果、 。私はTrackeronRenderedなどのトリックを試してみましたが、どれもうまくいきませんでした。これは、より多くのハックと見なすことができますが、動作します。残念ながら、私はこのソリューションが最初にどこにあるかを覚えていません。

テンプレートで開始しますが、eachの後ろにテンプレートタグを追加してください。

<template name="content"> 
{{#if Template.subscriptionsReady}} 
    {{#each currentData}} 
     <div data-cid="{{this._id}}"></div> 
    {{/each}} 
    {{doneTrigger}} 
{{else}} 
    Loading... 
{{/if}} 
</template> 

次に、nullを返すヘルパーを定義します。

Template.content.helpers({ 
    doneTrigger: function() { 
    Meteor.defer(function() { 
     // do what you need to do 
    }); 
    return null; 
    } 
}); 

あなたはMeteor.defer()hereについての詳細を読むことができますが、それは0ミリ秒setTimeoutを使用するのと同じです。

+0

これはまた、非常に良いと簡単なソリューションです、ありがとう! – ant45de

+0

これは、 '#each'の同期性質を使用しています。興味深いですが、Blazeの更なるアップデートに耐えられるかもしれません! –

+0

実際、言及したように、私はこの時点でこれ以上のハックを考えています。それは仕事を完了しますが。見られる。 –

3

スペースバーの{{#each}}ブロックが、繰り返し処理されるすべてのアイテムをDOMにレンダリングしたときに、通知を受け取る簡単な方法はありません。

他の反応計算(Tracker.autorun)を使用して、(無効な)現在のデータを観察することをお勧めします。

現在のデータ(カーソルの可能性が高い)が変更されるたびに、Tracker.afterFlushを使用して、他のすべての反応計算が完了した後に任意のコードを実行できます。

{{#each}}ブロックは、引数として与えた反応的なデータソースをリッスンし、反復処理中のソースからフェッチしたものと同じ回数だけ現在のアイテムを再レンダリングする役割を果たす計算の1つです。現在のデータコンテキスト。

{{#each}}ブロックヘルパーとまったく同じ反応データソースをリッスンし、独自の反応計算を完了した後にコードを実行すると、奇妙なトリックに頼らずに実際に要求された動作を得ることができます。ここで

は、このパターンの完全な実装です:

JS

Template.content.helpers({ 
    currentData: function(){ 
    return Template.currentData(); 
    } 
}); 

Template.content.onRendered(function(){ 
    this.autorun(function(){ 
    var cursor = Template.currentData(); 
    // we need to register a dependency on the number of documents returned by the 
    // cursor to actually make this computation rerun everytime the count is altered 
    var count = cursor.count(); 
    // 
    Tracker.afterFlush(function(){ 
     // assert that every items have been rendered 
     console.log(this.$("[data-cid]") == count); 
    }.bind(this)); 
    }.bind(this)); 
}); 
+0

私はこのソリューションが好きで、使いやすいと思うので、ありがとう!私はすでに各項目を自分の問題で十分にした後にコールバックを実現したので、{{#each}}の中でテンプレートを使用することに決めました。 – ant45de

0

また、サブテンプレートを使用してレンダリングされたサブテンプレートの数をカウントすることができます。この数値がコレクション内のアイテムの数である場合、すべてがレンダリングされます。それと

<template name="content"> 
{{#if Template.subscriptionsReady}} 
    {{#each currentData}} 
     {{> showData}} 
    {{/each}} 
{{else}} 
    Loading... 
{{/if}} 
</template> 

<template name="currentData"> 
    <div data-cid="{{this._id}}"></div> 
</template> 

、反応変数を初期化し、それを追跡:currentDataテンプレートがレンダリングされると

var renderedCount = new ReactiveVar(0); 

Tracker.autorun(function checkIfAllRendered() { 
    if(renderedCount.get() === currentData.count() && renderedCount.get() !== 0) { 
    //allDataRendered(); 
    } 
}); 

、それをインクリメントし、それが破壊されたときにそれをデクリメントします。

Template.currentData.onRendered(function() { 
    renderedCount.set(++renderedCount.curValue); 
}); 

Template.currentData.onDestroyed(function() { 
    renderedCount.set(--renderedCount.curValue); 
}); 
-1

Aを検討する可能性が単純なアプローチ - あなたの#eachブロックの周りにテンプレートを作成し、その後onRenderedイベントを取得:

HTML:

<template name="content"> 
{{#if Template.subscriptionsReady}} 
    {{> eachBlock}} 
{{else}} 
    Loading... 
{{/if}} 
</template> 

<template name="eachBlock"> 
{{#each currentData}} 
    <div data-cid="{{this._id}}"></div> 
{{/each}} 
</template> 

JS:

Template.eachBlock.onRendered(function(){ 
    console.log("My each block should now be fully rendered!"); 
}); 
関連する問題