Sato
Sato

Reputation: 8622

How to deal with the situation that template is rendered but the data is not ready?

In client startup I subscribe to something:

Meteor.publish("Roles", function(){
  return Roles.find();
});

Meteor.startup(function() {
  if(Meteor.isClient) {
    Meteor.subscribe('Roles');
  }
});

And roles template:

Template.roles.helper(function() {
  allRoles: function() {
    return Roles.find().fetch();
  }
})

<template name="roles">
  <div>
    {{#with allRoles}}
      <label>{{> role }}</label>
  </div>
</template>

The problem is sometime roles template is rendered before the Roles is ready.

How to deal with this situation?

Upvotes: 0

Views: 51

Answers (2)

illuminaut
illuminaut

Reputation: 320

There are some common ways of dealing with it. You can use a guard or make use of iron router's waitOn function. With a guard you only return data from the helper if you're getting any results:

allRoles: function() {
    var roles = Roles.find();
    //explicit version
    if (roles.count()) return roles

    //implicitly works as well here because you're returning null when there are no results
    return roles
}

You don't need the fetch() in this case, because #with works with a cursor. If you run into a situation where you need to fetch first because you're returning partial data, check that there are results first and only then return them.

You can also use iron router's waitOn Option if you're using this as part of a route.

Upvotes: 0

Jeff Lau
Jeff Lau

Reputation: 358

You can do the subscribe on the template and then use the Template.subscriptionReady helper to create a conditional to show a loading panel whilst your subscription is being loaded as follows:

Template.roles.onCreated(function () {
  this.subscribe("Roles");
});

Template.roles.helper(function() {
  allRoles: function() {
    return Roles.find().fetch();
  }
})

<template name="roles">
  <div>
    {{#if Template.subscriptionsReady}}
      {{#with allRoles}}
      <label>{{> role }}</label>
    {{else}}
      Loading...
    {{/if}}
  </div>
</template>

This replaces your other subscription and these subscriptions can be added to each onCreated method for each template to have subscriptions per template.

Upvotes: 2

Related Questions