Unlike Iron Router, FlowRouter doesn’t handle subscriptions at all. So in our second video, we’ll focus on going from router-level subscriptions to template-level subscriptions.

Global Subscriptions

We can divide subscriptions in a typical Meteor app into two kind: “global” subscriptions and “local” subscriptions.

Global subscriptions need to be loaded before the rest of your app. They typically include things like settings, or any data required by the app as a whole.

Iron Router gives you a waitOn callback in the Router.configure block to indicate a global subscription:

Router.configure({
  layoutTemplate: 'layout',
  loadingTemplate: 'loading',
  notFoundTemplate: 'notFound'
  waitOn: function () {
    return [
      Meteor.subscribe('site', SITE_KEY),
      Meteor.subscribe('toc'),
      Meteor.subscribe('chapters', BOOK_KEY),
      Meteor.subscribe('interviews', BOOK_KEY),
      Meteor.subscribe('videos', BOOK_KEY),
      Meteor.subscribe('thisUser'),
      Meteor.subscribe('pages')
    ];
  }
});

With template-level subscriptions, we’ll get rid of this waitOn block and instead create a helper that waits on these global subscriptions:

Template.layout.onCreated(function () {
  var template = this;
  template.autorun(function () {
    template.subscribe('site', SITE_KEY);
    template.subscribe('toc');
    template.subscribe('chapters', BOOK_KEY);
    template.subscribe('interviews', BOOK_KEY);
    template.subscribe('videos', BOOK_KEY);
    template.subscribe('thisUser');
    template.subscribe('pages');
  });
});

Template.layout.helpers({
  appReady: function () {
    return Template.instance().subscriptionsReady();
  }
});

And then use it in your layout template:

<template name="layout">
  {{#if appReady}}
    <!-- your app content -->
  {{else}}
    {{> loading}}
  {{/if}}
</template>

Note that we could use the default Template.subscriptionsReady() helper provided by Meteor out of the box, but just in case we later need to wait on some other conditions, I decided to create my own appReady helper.

Local Subscriptions

Local subscriptions look pretty much the same, except we also need to replace the data callback provided by Iron Router (more on this in the next video).

We used to wait on the subscription and set the data context at the router level:

this.route('user', {
  path: '/user/:_id',
  template: 'profile'
  waitOn: function () {
    Meteor.subscribe('user', this.params._id);
  },
  data: function () {
    return {
      user: Meteor.users.findOne({_id: this.params._id})
    };
  }
});

But now, we’ll get rid of both waitOn and data callbacks and instead do both at the template level:

Template.profile.onCreated(function () {
  var template = this;
  template.autorun(function () {
    template.subscribe('user', Router.current().params._id);
  });
});

Template.profile.helpers({
  ready: function () {
    return Template.instance().subscriptionsReady();
  },
  user: function () {
    return Meteor.users.findOne({_id: Router.current().params._id})
  },
});
<template name="profile">
  {{#if ready}}
    {{#with user}}
      <!-- show user profile here -->
    {{/with}}
  {{else}}
    {{> loading}}
  {{/if}}
</template>