By Oleksii Rudenko September 30, 2015 9:47 PM
Router service for Ember Apps

There is a repository where all new features of Ember are discussed and shaped before they are implemented and released. Recently Edward Faulkner published a RFC that describes a public Router service. I think it’s a great idea and I decided to prepare my apps for this change because I am 90% sure that we will see the router service in future releases of Ember.

What can we do now in order to adapt more easily to this change? Let’s create a simple service that wraps existing private -router service (yes, there is one):

//app/services/router.js
import Ember from 'ember';

const {computed} = Ember;
const {alias} = computed;

// Events to trigger/catch events
const RouterService = Ember.Service.extend(Ember.Evented,
{
  /*
  * Inject Ember's private routing service
  */
  routing: Ember.inject.service('-routing'),

  /**
  * Reference to an EmberRouter
  */
  router: alias('routing.router'),

  /**
  * Use EmberRouter to watch transitions
  */
  init: function(...args) {
    this._super(...args);
    const router = this.get('router');
    router.on('willTransition', (transition) =>
      this.trigger('currentPathWillChange', transition));
    router.on('didTransition', () =>
      this.trigger('currentPathDidChange', router.get('url')));
  },

  /**
  * API we expose
  * and events
  * + currentPathDidChange(currentPath)
  * + currentPathWillChange(transition)
  */
  transitionTo(...args) {
    return this.get('routing').transitionTo(...args);
  }

  /**
  * Other methods
  */

});

export default RouterService;

Additionally, the service requires an instance initializer in order to create an instance of the service before the routing phase starts and in order to be able to catch initial route transitions:

export function initialize(instance) {
  instance.container.lookup('service:router');
}

export default {
  name: 'router',
  initialize: initialize
};

Normally, services are created lazily so without the initializer the router service instance may not be created at all.

The above code implements only some methods that I often need. But it can be extended if needed.

So the idea is to follow RFC/current implementation of Ember and replace this service with the public Router service by the Ember team once it’s released. And I think it’s a good abstraction even if the Ember team decides to keep the Router service private.

See the service in action in this jsbin: http://emberjs.jsbin.com/voyalu/edit?html,js,console,output and in the blog post about the tracking service.

Thanks for reading.