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
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.