John T
John T

Reputation: 2677

Meteor JS Template rendered function called before template is rendered?

I'm trying to use the Buttonset widget in JQuery UI. I've got the package loaded and my template renders the radio buttons fine. I have a "rendered" function to call the JQ UI routine to setup the buttonset:

Template.teamList.rendered = function () {
    $("#buttonsetID").buttonset();
}

But it looks like the rendered function is being called before the template is rendered! I stick a console.log in the function and it prints out to the console before there's anything on the screen. So none of the radio buttons are set up, therefore the .buttonset() call does nothing. If I make that call in the console after the page is rendered, JQuery UI does the right thing and my button set appears.

Isn't the .rendered function supposed to be called after everything's set up? Am I doing something wrong?

Thanks!

edit:

As an example, the same thing is seen in the leaderboard example.

If you add:

  Template.leaderboard.rendered = function() {
     alert($('.player').length);
  }

When the page is displayed, it will show 0. This makes it difficult to access the DOM items if you need to add some JQuery events or, in this case, a JQuery UI element.

Upvotes: 1

Views: 3195

Answers (1)

David Weldon
David Weldon

Reputation: 64312

rendered only works for elements which will appear in the DOM the very first time the template is added to the page. Assume that subscription data takes infinitely long to arrive, then look at the template and see which elements would appear in the default state.

Using the leaderboard example, we can't assume that players are available when the leaderboard template renders (it depends on a subscription). To target a player, you should use the rendered callback on the player template.

It's hard to generalize a strategy for when to apply jQuery plugins, but here are some ideas:

  • Use the rendered callback if the element will always be added in the default state (e.g. the element is hard-coded and doesn't depend on a conditional).

  • Use the rendered callback of the most specific child template to target that child (e.g. the player template from above).

  • Consider using an event handler callback to target the element if it's appearance depends on an event (e.g. a button click).

  • Consider using a template autorun callback to target the element if it's appearance depends on reactive state. See this question for an example.

Upvotes: 3

Related Questions