EventAggregator inside Service without a View Not Working

I’m trying to create a service which subscribes to an event and fires whenever the event occurs. I’m able to get the whole thing working if I create an empty view template for the service and put the subscription in the attached() function.

However if there is no view template, there’s no attached function called and I need to register the subscription somewhere. I tried creating the following class:

service.js

import {inject} from 'aurelia-framework';
import {EventAggregator} from 'aurelia-event-aggregator';

@inject(EventAggregator)

export class Service {

  constructor(EventAggregator) {
    this.ea = EventAggregator;
  }

  registerSubscription = () =>
  {
    let subscription = this.ea.subscribe('someEvent', () => {
      console.log('Service triggered');
    });
  }
}

And registering the subscription in the constructor of the app:
app.js:

import {Service} from './modules/test/services/service'

export class App {
  constructor() {
    this.service = new Service;
    this.service.registerSubscription()
  }
}

Message: Cannot read property ‘subscribe’ of undefined
Inner Error Stack:
TypeError: Cannot read property ‘subscribe’ of undefined
at Service.registerSubscription (webpack-internal:///+xuG:16:33)
at new App (webpack-internal:///app:7:16)
at Object.invoke (webpack-internal:///3U8n:464:12)

If I can’t register it here, do you have any suggestions of where I could register it? I also tried registering it in a method of the same class which I call in the classes constructor and I get the same error.

The error is because the way you constructed your Service instance. When doing new Service, you didn’t give it the necessary instance of EventAggregator. What you should do is to use dependency injection for Service like following block:

@inject(Service)
export class App {
  constructor(service) {
    this.service = service;
    service.registerSubscription();
  }
}
2 Likes

Excellent it’s working now thanks!

For services that consume events like this, is registering it in the App constructor the best approach or is there some other pattern that makes more sense?