raddevon
raddevon

Reputation: 3360

How do I run client-side code after a new collection item has been added to a Meteor view?

In my template, I call a server-side method to add an item to a collection. This collection is displayed on the page. Once the new item is rendered, I want to focus it for the user.

Here's the helper that fires the server method.

'click .add-post-button': function(e) {
  var userId = Template.parentData(0)._id;
  Meteor.call('addPost', userId, function(error, result) {
    Session.set('newPostId', result);
  });
}

Once this is finished, the new item appears. I want to focus it for the user. Previously, I tried to do it in the callback above with jQuery, but that didn't work because it had not been added to the DOM by the time the callback ran. Now, I'm trying to use the rendered callback:

Template.postsAdmin.rendered = function() {
  var newPostId = Session.get('newPostId');
  if (newPostId) {
    var $newPostCell = $('#' + newPostId);
    $newPostCell.find('.post').focus();
  }
};

Unfortunately, this doesn't seem to be working either. This code does not run when the new item is added to the view.

How can I run code after the new item has been added to the view in order to focus the new item?

Upvotes: 1

Views: 159

Answers (2)

David Weldon
David Weldon

Reputation: 64342

Your original code is really close - you just need to put the focus logic into a reactive context so it will run again with the session variable changes. The shortest path to success is to use a template autorun:

Template.postsAdmin.onRendered(function() {
  this.autorun(function() {
    var newPostId = Session.get('newPostId');
    if (newPostId) {
      var $newPostCell = $('#' + newPostId);
      return $newPostCell.find('.post').focus();
    }
  });
});

However, one problem you may run into is that you'll have a race condition where the new post is added after the autorun fires. A hacky solution is to add a timeout to the above. An improved solution is to add something like your original code to the onRendered callback of the newly added post sub-template:

Template.post.onRendered(function() {
  var newPostId = Session.get('newPostId');
  if (newPostId === this.data._id) {
    // add code here to focus this template instance
  }
});

Upvotes: 2

Sasikanth
Sasikanth

Reputation: 3043

One option may be observeChanges? Can you try this?

in the rendered function do following

Template.postsAdmin.rendered = function(){

   var query = Posts.find({}); //your query
   var handle = query.observeChanges({
       added: function (id, user) {
          //code to set focus???
       }
   });
}

This code runs whenever there is a new item addeded to minimongo which matches your query.

Make sure to show the template after you load the data.

docs link http://docs.meteor.com/#/full/observe_changes

Upvotes: 1

Related Questions