Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to subscribe to an event on a service in Angular2?

I know how to raise an event with the EventEmitter. I can also attach a method to be called if I have a component like this:

<component-with-event (myevent)="mymethod($event)" />

When I have a component like this, everything works great. I moved some logic into a service and I need to raise an event from inside the Service. What I did was this:

export class MyService {
  myevent: EventEmitter = new EventEmitter();

  someMethodThatWillRaiseEvent() {
    this.myevent.next({data: 'fun'});
  }
}

I have a component that needs to update some value based on this event but i can't seem to make it work. What I tried was this:

//Annotations...
export class MyComponent {
  constructor(myService: MyService) {
    //myService is injected properly and i already use methods/shared data on this.
    myService.myevent.on(... // 'on' is not a method <-- not working
    myService.myevent.subscribe(.. // subscribe is not a method <-- not working
  }
}

How do i make MyComponent subscribe to the event when the service that raises it is not a component?

I'm on On 2.0.0-alpha.28

EDIT: Modified my "working example" to actually work, so focus can be put on the not-working part ;)

Example code: http://plnkr.co/edit/m1x62WoCHpKtx0uLNsIv

like image 998
Per Hornshøj-Schierbeck Avatar asked Sep 27 '22 09:09

Per Hornshøj-Schierbeck


People also ask

Can we subscribe to an event in angular?

Angular will subscribe to the add event and call the addTodo() method with the data when the component triggers the next() method.

Can you subscribe to event emitter?

subscribe() is an EventEmitter method that registers handlers for events emitted by this instance. subscribe() have three optional parameters which can be used to pass values, errors, or completion notification in EventEmitter .

What is difference between subject and EventEmitter?

Conclusion. Use Eventemitter when transferring data from child component to parent component. Use Subject to transfer data from one component to another component.

How do you emit an event from one component to another?

In @angular/core, we have @Output and EventEmitter which allow us to emit event from one component to another. Let us see how to do this. Say there is a button inside the child component and we create a variable index which is passed as the parameter of the event.


1 Answers

Update: I have found a better/proper way to solve this problem using a BehaviorSubject or an Observable rather than an EventEmitter. Please see this answer: https://stackoverflow.com/a/35568924/215945

Also, the Angular docs now have a cookbook example that uses a Subject.


Original/outdated/wrong answer: again, don't use an EventEmitter in a service. That is an anti-pattern.

Using beta.1... NavService contains the EventEmiter. Component Navigation emits events via the service, and component ObservingComponent subscribes to the events.

nav.service.ts

import {EventEmitter} from 'angular2/core';
export class NavService {
  navchange: EventEmitter<number> = new EventEmitter();
  constructor() {}
  emitNavChangeEvent(number) {
    this.navchange.emit(number);
  }
  getNavChangeEmitter() {
    return this.navchange;
  }
}

components.ts

import {Component} from 'angular2/core';
import {NavService} from '../services/NavService';

@Component({
  selector: 'obs-comp',
  template: `obs component, item: {{item}}`
})
export class ObservingComponent {
  item: number = 0;
  subscription: any;
  constructor(private navService:NavService) {}
  ngOnInit() {
    this.subscription = this.navService.getNavChangeEmitter()
      .subscribe(item => this.selectedNavItem(item));
  }
  selectedNavItem(item: number) {
    this.item = item;
  }
  ngOnDestroy() {
    this.subscription.unsubscribe();
  }
}

@Component({
  selector: 'my-nav',
  template:`
    <div class="nav-item" (click)="selectedNavItem(1)">nav 1 (click me)</div>
    <div class="nav-item" (click)="selectedNavItem(2)">nav 2 (click me)</div>
  `,
})
export class Navigation {
  item = 1;
  constructor(private navService:NavService) {}
  selectedNavItem(item: number) {
    console.log('selected nav item ' + item);
    this.navService.emitNavChangeEvent(item);
  }
}

Plunker

like image 159
Mark Rajcok Avatar answered Oct 23 '22 09:10

Mark Rajcok