Friendly Forwarding the Meteor Way

A few days ago I wrote about this very topic using redirects with FlowRouter without checking whether it was the Meteor Way of doing it. It turned out that redirects are frowned up in Meteor. So I set out to find out how to do it the Meteor Way.

The Problem

The application I am developing requires registration, sign in and sign out. The application also has a landing page as well as a home page. The landing page, the registration page and the sign in page do not require authentication. Upon successful sign in/sign up the user is redirected to the home page. All other pages require authentication before being rendered.

If the user types the url of a page she/he wants to visit without out authentication the sign in page is rendered. Upon successful sign in, I want to send the user to the page she/he wanted to visit. This is where I used redirect in the previous article and in this article I am going to demonstrate the solution I found for single page application (SPAs).

The Setup

For the purpose of this demonstration I am going to assume that there is a route called 'list' and the corresponding template it renders also called 'list'. And here is the relevant route definitions:

const authenticatedRoutes = FlowRouter.group({  
  triggersEnter: [ function() {
    if (!Meteor.loggingIn() && !Meteor.userId()) {
      FlowRouter.go('signin');
    }
  } ]
});

FlowRouter.route('/signin', {  
  name: 'signin',
  action() {
    BlazeLayout.render('application', {
      nav: 'nav',
      noauth: 'signin',
      footer: 'footer'
    });
  },
});

authenticatedRoutes.route('/list', {  
  name: 'list',
  action() {
    BlazeLayout.render('application', {
      nav: 'nav',
      main: 'list',
      footer: 'footer'
    });
  },
});

And here is the content of the layout file:

<template name="application">  
  {{> Template.dynamic template=nav}}
  {{> Template.dynamic template=main}}
  {{> Template.dynamic template=noauth}}
  {{> Template.dynamic template=footer}}
</template>  

The easiest way I found for dealing with the routes that require authentication versus those that do not was to add the line:

{{> Template.dynamic template=noauth}}

to the layout file.

Forwarding the User

Whenever the user signs in successfully, the 'home' template is rendered but, if she/he tried to go to 'list' without being authenticated then the 'list' page has to be rendered. This is how I defined my 'home' template:

<template name="home">  
  {{#if destination}}
    {{> Template.dynamic template=main}}
  {{else}}
    Content of home page goes here
  {{/if}}
</template>  

The 'destination' and 'main' are defined as a helper function and they look like this:

Template.home.helpers({  
  destination: function() {
    return Session.get('destination');
  },
  main: function() {
    const destination = Session.get('destination');
    if (destination) {
      Session.set('destination', undefined);
      return destination;
    }
  },
});

The 'destination' session' key is set in the signin.js file like so:

Template.signin.onCreated(function() {  
  const current = FlowRouter.current();
  const oldRoute = current.oldRoute;
  if (oldRoute) {
    Session.set('destination', oldRoute.name);
  }
});

And that is all there is to it!

Comparison of the Approaches

Other than being a bad practice in SPAs the main difference between the two approaches is that the redirects define the logic in the router using triggers while the “Meteor way” defines the logic at the template level. The “Meteor Way” is quite straight forward to implement.

The FlowRouter documentation states the this could be implemented at the layout level, but I have not investigated that approach as yet.

As always suggestions and comments are welcome.

Emmanul Asante

Read more posts by this author.

Subscribe to Meteor University

Get the latest posts delivered right to your inbox.

or subscribe via RSS with Feedly!