Subscriptions & Routers in Meteor

I’m building a simple (learning) app using Iron Router (because it was suggested by the book), so all of my subscriptions are managed by Iron Router.

I’m a bit confused, though, since Iron Router is a third-party package (i.e. not part of Meteor core), about where would I subscribe to Mongo collection publications if I were not using a router? I mean, I haven’t used Flow Router (yet) but I assume it has a similar method for subscribing to publications.

But if your app were not using any router, how (and where) would you subscribe to data publications?

Also, just a reality check here: my understanding is that if you did not use any router package in your app, you would essentially have a Single-Page App, right? I mean, there would be no URLs or navigation, per se, within your app - all templates would be rendered and replaced within a single page/view, right?

If that isn’t correct, how would an app with no router work?

A router is a utility that basically provides a shareable structured piece of text representation of the parts of an application’s state which you want to be able to reproduce at any given time.

A single page app can do the same by relying on other utilities to achieve the same goal. It can be the Session, a cookie, browser’s localstorage, meteor’s reactive dict. The sharing part would be not as straightforward, though, but you’d still be able to manage an overall state.

Take this example:

javascript

if (Meteor.isClient) {
  Template.pager.onCreated(function(){
    Session.setDefault('page', 'pageOne');
  })
  Template.pager.helpers({
    currentPage: function(pageName){
      return Session.get('page') === pageName;
    }
  })
  Template.pager.events({
    'click [data-pager]': function(e,t){
      Session.set('page', e.target.value);
    }
  })
}

html

<template name="pager">
  <a href="#" data-pager="one">Go to page 1</a>
  <a href="#" data-pager="two">Go to page 2</a>
  {{#if currentPage "one"}}
    {{>pageOne}}
  {{/if}}
  {{#if currentPage "two"}}
    {{>pageTwo}}
  {{/if}}
</template>
<template name="pageOne">
  Page One
</template>
<template name="pageTwo">
  Page Two
</template>

There of course are much better ways of achieving this like Template.dynamic or Blaze.render but that’s a nice exercise for you :wink:

So as you see, we were able to reproduce the effect of a router by merely acting on the clicks on our navigation links and setting a session variable, all the while, checking the current value of the session to decide which page (template) we want to reveal.

By the way, the example about would be a good example for you to change the use of Session to a reactive var or reactive dict.

Now, about the subscriptions. You can subscribe to a publication anywhere, as long as you are on the client. That means, you don’t have to be within a router. In fact, anywhere is fine. Even an arbitrary place in your client javascript would work.

But, Meteor supports template level subscriptions so that you can subscribe to template specific data whenever you actually need it, that’s right before rendering the template.

So here’s an example with a global subscription that’s available to the whole app as soon as the app loads, and a template level subscription, that just activates when needed.

javascript

Meteor.startup(function(){
  Meteor.subscribe('globalData');
})
Template.pageOne.onCreated({
  this.subscribe('pageOneData');
})

html

<template name="pageOne">
  Page One
  {{#if Template.subscriptionsReady}}
    Show some data...
  {{/if}}
</template>

So you see, we don’t need a router either for navigating within the app, nor for subscriptions.

But, that being said, a router is always a nice tool which makes app navigation a breeze.

For subscriptions, the current trend is template level subscriptions. You don’t subscribe to data within the router. Flow router has set out to deprecate its router level subscription support in version 3.0 for example.

1 Like