Angular 2 - How to listen to event without a template?

Problem

The Problem

Normally, in Angular 2, one would listen to an event via the following syntax:

<my-elem (customEvent)="customEventProcessor"></my-elem>

But when I use a router, that host - <my-elem> - does not exist in any template. Instead, there's a <router-outlet>, and my component is loaded upon navigation. Thus, the crux of my problem is, How can I force my host to listen to my custom event without relying on a template?

Optional Details

Suppose I have some element list-view, which is a child of my root component. list-view listens for a custom event via the normal syntax:

<list-view (customEvent)="customEventProcessor()"></list-view>

Just for completeness, the list-view component that emits the event also has a predictable structure:

<button (click)="onDetailsClick(propertyOfInterest)">Click here</button>

The list-view sends the event up to the parent via observation.

class ListView {

    ...

        public onDetailsClick(property: string): void {

            this.customEvent.next({ value: property });

        }

}

and that event triggers the customEventProcessor() function. So far so good. However, when I use a router to control whether list-view is present, I cannot (to my knowledge) insert a command to monitor some event.

I am not sure what the best approach is to handle this case.

Problem courtesy of: Jefftopia

Solution

This problem isn't resolved yet (see this github issue). Here is one of the possible solutions at this moment (see this plunk):

@Component({
  selector: 'my-app',
  directives: [RouterOutlet, RouterLink],
  template: `
    <h1>{{ message }}</h1>
    <a [router-link]="['./MyElem1']">MyElem1</a>
    <a [router-link]="['./MyElem2']">MyElem2</a>
    <router-outlet></router-outlet>
  `
})
@RouteConfig([
  { path: '/', redirectTo: '/my-elem1' },
  { path: '/my-elem1', name: 'MyElem1', component: MyElem1 },
  { path: '/my-elem2', name: 'MyElem2', component: MyElem2 },
])
export class App {
  message: string = 'Click on the button';

  @ViewChild(MyElem1) myElem1: MyElem1;
  @ViewChild(MyElem2) myElem2: MyElem2;

  constructor(router: Router) {
    let subs = null;
    router.subscribe(() => {
      if (subs) { subs.unsubscribe(); subs = null; }

      if (this.myElem1) {
        subs = this.myElem1.customEvent1.subscribe(m=>this.processCustomEvent(m));
      }
      if (this.myElem2) {
        subs = this.myElem2.customEvent2.subscribe(m=>this.processCustomEvent(m));
      }
    });
  }

  processCustomEvent(message) { this.message = message }
}
Solution courtesy of: alexpods

Discussion

There is currently no discussion for this recipe.

This recipe can be found in it's original form on Stack Over Flow.