it-swarm.com.de

Winkel 4, der ein Ereignis in einem gemeinsam genutzten Dienst ausstrahlt und abonniert

Ich stelle ein Ereignis in meiner Hauptkomponente aus:

hauptkomponente.ts

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

Hier ist meine sharedService.ts

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

In meiner anderen (Teil-) Komponente möchte ich auf diesen Wert zugreifen, aber irgendwie funktioniert das Abonnement nicht:

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));
}

Fehlt mir etwas? Es funktioniert einwandfrei, wenn ich die Daten als Injectable übergeben habe. Das Auslösen des Ereignisses (in der Hauptkomponente) geschieht nach einigen REST - Aufrufen.

Update

Das Problem ist also, dass die Unterkomponente nach der ersten Ausgabe des Ereignisses erstellt wird. Ich denke, in diesem Fall ist es besser, die Daten direkt in die subcompnent zu injizieren.

4
Stef

Update: Plunker-Beispiel nicht mehr gepflegt, bitte StackBlitz .__ verwenden. Beispiel hier https://stackblitz.com/edit/stackoverflow-fragen-45351598-angular?file=src%2Fapp%2Fapp.component.ts

Ich habe ein funktionierendes Plunker-Beispiel mit dem oben angegebenen Code erstellt. 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 {}

Lebenszyklus-Hooks hier anzeigen https://angular.io/guide/lifecycle-hooks

6
J J B

Versuche dies: 

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

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

Das bedeutet, dass der zuletzt ausgegebene Wert für den "späten" Abonnenten wiedergegeben wird . Wenn ein Anfangswert ausgegeben werden soll, können Sie BehaviourSubject verwenden.

Oder Sie können es mit dem Operator startWith pfeifen/ketten.

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