Using Services in Services in Ember

Using Services in Services in Ember

Mar 29, 2016
Javascript, Ember

Ember now has the concept of services which are incredible useful and the documentation for how to use them is good. What, however, is not so well covered is how to include a service within a service. In my previous blog post Building an Ember Message Bus I showed how to create an event bus service and inject it into routes, controllers, components and models. However, I soon discovered that the particular work application I was working on I need to be able to access the event bus service from within one of my other services. While this is not difficult there were a couple of gotchas.

When you create a service with ember-cli using the ember generate command then the service name has to be hyphenated, as follows:

ember generate service service-name

In the particular place were I work we use vx as the first part of the name of our components and then use s as the next letter if it is a service, so for the sake of this blog post we will name the event bus service vxs-eventbus and the service I want to use the event bus service in vxs-consumer.

Now that I had my two service I thought, cool, this should be easy. So in vxs-consumer I had:

import Ember from 'ember';

export default Ember.Service.extend({
    name: 'vxs-consumer',
    eventbus: Ember.inject.service('vxs-eventbus'),
    etc...

but that didn’t work. After doing some more reading and chatting to Alex Speller on the ember IRC channel, I figure it out. Basically, the key to remember is that Ember uses convention over configuration. It makes sense once you see it, but not always before.

To get it to work I needed to do:

import Ember from 'ember';

export default Ember.Service.extend({
    name: 'vxs-consumer',
    vxsEventbus: Ember.inject.service(),
    etc...

Now Ember looks at this and goes, OK, I need to inject a service, but which one. So it takes the vxsEventbus and by convention changes that to vxs-eventbus, and voila, your service now can use the event bus service. Using it is exactly the same as in the normal case:

this.get('vxsEventbus').publish('_eventName', data);

where _eventName is the event you want to trigger and the data you want to pass is in data, which is an optional parameter.