Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular 4 emitting and subscribing to an event in a shared service

I am emitting an event in my main component:

main.component.ts

this.sharedService.cartData.emit(this.data);

Here is my sharedService.ts

import { Component, Injectable, EventEmitter } from '@angular/core';
export class SharedService {
    cartData = new EventEmitter<any>();
} 

In my other (Sub) Component, I want to access this value, but somehow, the subscription does not work:

dashboard.ts

private myData: any;

constructor(private sharedService: SharedService) {
    this.sharedService.cartData.subscribe(
        (data: any) => myData = data,
        error => this.errorGettingData = <any>error,
        () => this.aggregateData(this.myData));
}

Am I missing something? It works fine when I pass the data as an Injectable. Emitting the event (in the main component) happens after some REST calls.

Update

So the problem is that the Subcomponent is created after the first emit of the event. I guess in this case it is better to inject the data into the subcompnent directly.

like image 693
Stef Avatar asked Jul 27 '17 13:07

Stef


People also ask

Can a service emit an event?

Services emit events for resources or data. For example, Object Storage emits events for buckets and objects. Services emit different types of events for resources, which are distinguished as event types.

Can we subscribe an EventEmitter in Angular?

EventEmitterlink. Use in components with the @Output directive to emit custom events synchronously or asynchronously, and register handlers for those events by subscribing to an instance.

How do event emitters work in Angular?

๐ŸŽŠ Event Emitters in Angular ๐ŸŽŠData flows into your component via property bindings and flows out of your component through event bindings. If you want your component to notify his parent about something you can use the Output decorator with EventEmitter to create a custom event.

What is difference between subject and EventEmitter?

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


1 Answers

Update: Plunker example no longer maintained please use StackBlitz example here https://stackblitz.com/edit/stackoverflow-questions-45351598-angular?file=src%2Fapp%2Fapp.component.ts

I have created a working plunker example using the code you provided above. https://plnkr.co/edit/LS1uqB?p=preview

import { Component, NgModule, Injectable, EventEmitter, AfterViewInit } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';


@Injectable()
export class SharedService {
    cartData = new EventEmitter<any>();
} 

@Component({
  selector: 'app-app',
  template: `
    <h1>
      Main Component <button (click)="onEvent()">onEvent</button>
    </h1>
    <p>
      <app-dashboard></app-dashboard>
    </p>
  `,
})
export class App implements AfterViewInit {
  data: any = "Shared Data";

  constructor(private sharedService: SharedService) {
  }

  ngAfterViewInit() {
    this.sharedService.cartData.emit("ngAfterViewInit: " + this.data);
  }

  onEvent() {
    this.sharedService.cartData.emit("onEvent: " + this.data);
  }
}

@Component({
  selector: 'app-dashboard',
  template: `
    <h2>
      Dashboard component
    </h2>
    <p>
      {{myData}}
    </p>
  `,
})
export class AppDashboard implements AfterViewInit {
  myData: any;

  constructor(private sharedService: SharedService) {
          this.sharedService.cartData.subscribe(
          (data: any) => {
            console.log(data);
            this.myData = data;
          });
  }

}


@NgModule({
  imports: [ BrowserModule ],
  declarations: [ App, AppDashboard ],
  providers: [ SharedService ],
  bootstrap: [ App ]
})
export class AppModule {}

View lifecycle hooks here https://angular.io/guide/lifecycle-hooks

like image 120
J J B Avatar answered Oct 22 '22 00:10

J J B