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

廉价感情. 提交于 2019-12-07 05:23:43

问题


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.


回答1:


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




回答2:


Try this:

export class SharedService {
    private dataPusher = new Subject<any>();
    cartData = dataPusher.asObservable().pipe(shareReplay(1));

    pushData(value:any) {
       this.dataPusher.next(value);
    }
} 

What that does is that it will replay the last emitted value for the "late" subscriber. If you want to have a initial value being emitted, you could use BehaviourSubject - it takes initial value in the constructor.

Or you could pipe/chain it with startWith operator.

cartData = dataPusher.asObservable().pipe(startWith("someValue"), shareReplay(1));


来源:https://stackoverflow.com/questions/45351598/angular-4-emitting-and-subscribing-to-an-event-in-a-shared-service

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!