OnRendered runs before Template.subscriptionsReady

Hi,

Can someone aid in the solving of this puzzle for me. Or maybe lend an explanation of the behaviour.

<template name="calendarMobile">
  {{#if Template.subscriptionsReady}}
  <div id="calendar"></div>
  {{else}}
  Loading ..
  {{/if}}
</template>
Template.calendarMobile.onCreated(function () {
  var instance = this;

  instance.autorun(function () {
    var calendarId = FlowRouter.getParam('calendarId');
    instance.subscribe("events", calendarId);
  });
});

Please note : instance.subscribe is being used instead of Meteor.subscribe

Why therefore when am calling Events.find().fetch() within the onRendered definition, is the generated array empty ?! Only sometime later, does it actually get populated.

I was under the impression, that {{#if Template.subscriptionsReady}} would prevent the DOM creation of the template innards until the Template’s own subscriptions & thus data, have actually been populated; and this would in turn call the onRendered function of the Template.

Are the two (cursor vs data) mutually exclusive from a readiness point of view ?

Or is there something else that I am simply not understanding ?

All explanations welcome :slight_smile:

Thank you.

As I understand it, the Template.subscriptionsReady is part of the template and so by the time it is evaluated the template is rendered.

One idea that comes to mind is to use Template.subscriptionsReady inside an autorun in the onRendered.

Something like:

instance.autorun(function() {
  if (!Template.subscriptionsReady())  return;
  Events.find().fetch() 
}

You should push your rendering function down one template.

Make the component that subscribes to data the only thing it does. Then make some calendarComponent that will “render” when ready is called!

1 Like

Mate - that worked like a charm.

Thank you!!

When you get a minute; can you share why that is necessary; namely why do we have to be so granular, almost to the control / component for the template rendering and subscription management to work in concert?

Again, thank you; just want to understand the cause now.

Cheers.

1 Like

That’s because our data is traveling down a socket. And our code is running whenever the hell it wants.

When subscribe there is some
Latency until we get all our data, so it’s best not to make assumptions about what your UI can do before you get ready. I’ve been bitten in the past by making assumptions about subscription state only to have my data be undefined then a value later. Be granular. It’ll save you from killing someone

1 Like

can this be the new reactive programming motto please :joy:

Hi @abhiaiyer.

Wanted to provide a same granular feedback to the user with a loading spinner, and noticed that if I wrap the now atomic control in its own set of:

{{#if Template.subscriptionsReady}}
  <div id="calendar"></div>
{{else}}
  {{> loading}}
{{/if}}

The calendar control now completely fails to load. So looks like I have something else misconfigured.

I looked at the publication, and even added a this.ready(); at the end of the Event.find(); still no love.

Any thoughts on how to get that granular feedback of the subscriptionsReady now?

Thank you.