Ruben
Ruben

Reputation: 826

Add a loading indicator or spinner for rendering delay (Not for subscription ready)

My meteor app template is taking a 1 second delay between creation and rendering. The delay is after the data subscription is available, so it seems that the 1 second is the time required by Blaze to read the data locally and draw all the objects in DOM (Perhaps most of them are in cache).

The question is: There is a way to add a spinner in the loaded template to cover the delay between myTemplate.OnCreated and myTemplate.onRendered?

Thanks in advance. 0.5 sec delay in Blaze._materializeDOM

Upvotes: 0

Views: 898

Answers (2)

Ruben
Ruben

Reputation: 826

The solution was very similar in logic to @jordanwillis solution, just was needed to add a timeout on template created:

<template name="contactList">
   {{#if contactListRendered }}
      <!-- Here show the contact list -->
   {{else}}
      <!-- show loading indicator or spinner  -->
   {{/if}}
</template>

Logic:

Template.contactList.onCreated( function() {
   Session.set("contactListRendered", false);
});

Template.contactList.onRendered( function() {
   setTimeout(function(){Session.set("contactListRendered", true);}, 1);
});

Template.contactList.helpers({
   contactListRendered: function() {
   return Session.get("contactListRendered");
}}); 

Upvotes: 0

jordanwillis
jordanwillis

Reputation: 10705

There are a couple of ways to achieve what you are after and its a little difficult to pick the right one for your case without seeing more of your code.

But if you are not performing any specific logic in your template definition once your subscription is ready then you can use the Blaze Template.subscriptionsReady helper.

<template name="notifications">
  {{#if Template.subscriptionsReady}}
    <!-- put your view code here -->
  {{else}}
    <!-- put loading indicator here -->
  {{/if}}
</template>

If you are doing something special to your data once your subscription is ready, or if you need to wait until all the data is fully loaded then you can control when the Template renders using a ReactiveVar.

Template definition:

<template name="notifications">
  {{#if isReady }}
    <!-- put your view code here -->
  {{else}}
    <!-- put loading indicator here -->
  {{/if}}
</template>

Template logic:

Template.notifications.onCreated(function() {
  this.isReady = new ReactiveVar(false);
});

Template.notifications.onRendered(function() {
  this.subscribe('activeNotifications', () => {
    this.isReady.set(true);
  });
});

Template.notifications.helpers({
  isReady: function() {
    return Template.instance().isReady.get();
  },
});

I usually implement my loading indicator logic in its own Template so that I can re-use it across the site.

Upvotes: 1

Related Questions