2

I made a service named UserEvents

@Injectable()
export class UserEvents {

public evAuthenticated: EventEmitter<string> = new EventEmitter();

public AuthUserEvent(email: string) {
this.evAuthenticated.next(email);
  }
}

I included this service with the providers in AppModule

I have a service name AuthService that include the UserEvents and emits:

this.userEvents.evAuthenticated.emit(email);

And another service that suscribe

constructor(private userEvents: UserEvents){
this.userEvents.evAuthenticated.subscribe((data: string) => this.SetUser(data));
}

private SetUser(email: string) {
   this.logger.info('Event triggered with ' + email);
}

But the suscription is never triggered. At list, SetUser is never called.

What is wrong here?

jonrsharpe
  • 115,751
  • 26
  • 228
  • 437
Marcos
  • 231
  • 1
  • 5
  • 14
  • 3
    Dont use event emitter in your services: https://stackoverflow.com/questions/36076700/what-is-the-proper-use-of-an-eventemitter. Use a shared service instead: https://angular.io/guide/component-interaction#parent-and-children-communicate-via-a-service – eko Aug 20 '17 at 19:48
  • 1
    Use a Subject instead of EventEmitter – Denko Mancheski Aug 20 '17 at 20:15
  • EventEmitter inherits from Subject: `export declare class EventEmitter extends Subject {` – Guntram Oct 17 '17 at 08:04

3 Answers3

4

From my knowledge of Angular 2(+), EventEmitters are to be used as Component Outputs, i.e.:

 @Output() myStringOutput = new EventEmitter<string>();

If you need a triggerable event in your services, it is recommended to use RxJS Subjects, like so:

import { Injectable } from '@angular/core'
import { Subject } from 'rxjs/Subject';

@Injectable()
export class MyService {

  private _onMyEvent = new Subject<string>();
  public get onMyEvent(): Observable { return this._onMyEvent.asObservable(); }

  public trigger(value: string) {
    this._onMyEvent.next(value);
  }
}

And elsewhere in your code, you can do something like this:

this.myService.onMyEvent.subscribe((value: string) => console.log('Triggered!', value));
this.myService.trigger('Hello World')

Plunkr.

Michael Fedora
  • 556
  • 4
  • 10
1

Use Subject instead:

@Injectable()
export class UserEvents {

    public evAuthenticated = new Subject<string>();

    public AuthUserEvent(email: string) {
        this.evAuthenticated.next(email);
    }
}

Keep your subscription code as it is.

Check comment from Günter Zöchbauer on my answer here: https://stackoverflow.com/a/45710245/1791913

EventEmitter is not supposed to be used in services. An Observable or Subject does the same. EventEmitter is supposed to be used only for @Output()s. EventEmitter just extends Subject (AFAIR), but the Angular team can change this without prior notice to a custom implementation that still works for @Output() but might break other uses, because @Output() is the only thing EventEmitter is supposed to be used for.

FAISAL
  • 33,618
  • 10
  • 97
  • 105
0

Thanks for your help, but both are not required in Angular 4. I found the problem: the service that suscribe is not instanciated automatically. I added the service in the constructor of app.component and everything began to work.

Marcos
  • 231
  • 1
  • 5
  • 14