Marcos
Marcos

Reputation: 231

Angular 4 Events with EventEmitter

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?

Upvotes: 2

Views: 6294

Answers (3)

Marcos
Marcos

Reputation: 231

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.

Upvotes: 0

FAISAL
FAISAL

Reputation: 34673

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.

Upvotes: 1

Michael Fedora
Michael Fedora

Reputation: 556

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.

Upvotes: 4

Related Questions