Oleg Kiviljov
Oleg Kiviljov

Reputation: 113

Execute code after each loop finishes rendering items from collection

I am building basic chat application just to try out meteor. When user enters a chat channel, it would be logical to show him the latest messages that are at the bottom. Right now I am trying to achieve this with following code

Template manager

Template.messages.rendered = function(){
  var message_container = this.find('.messages');
  var height = message_container.scrollHeight;
  $(message_container).animate({scrollTop: height}, 1000)
};

Template

<template name="messages">
   <div class="messages">
     {{# each messages}}
   {{> message}}
     {{/each}}
   </div>
</template>

The problem is the code in template manager is being executed, while not all messages have been rendered, thus it results in incorrect height, in var height.

Upvotes: 0

Views: 254

Answers (1)

kaytrance
kaytrance

Reputation: 2757

This is similar bottleneck as with microscope demo app from Discover meteor book - the problem with rendered method is that you cannot tell for sure wheter this is fired when template with data finished rendering, or just template rendered before filled with data. The workaround may be to track message count in some local collection or just variable and in rendered check if current message count is greater that is was before. If so, scroll a window a bit down.

This method is used in chaper 14 (if I am not mistaked) of book above.

The simple dirty trick may be to just test a timeout in rendered, but I do not recomment to do so.

Oh, and one more dirty trick would be to add some invisible element to the end of the dom tree of your page so that all new messages should be inserted before it. Then just add an event handler on this element position change. Each time a new message is rendered it will push this element a bit down, therefore an event will be triggered. In that event handler add code to scroll down. Similar solution can be found here.

Upvotes: 1

Related Questions