I want to pass some data from one module to another module. For that I am using Subject. I have created below subject :
import { Injectable } from '@angular/core';
import { Subject } from 'rxjs';
@Injectable({
providedIn: 'root'
})
export class SelectedClusterService {
constructor() { }
public selectedClusterName = new Subject<string>();
}
I am passing some data from "oneComponent" through above service like this and redirect to "anotherComponent":
this.selectedClusterService.selectedClusterName.next(cluster_name);
And fetching data to "anotherComponent" like this:
this.selectedClusterService.selectedClusterName.subscribe(res => {
this.selectedCluster = res;
console.log("this.selectedCluster", this.selectedCluster);
});
This is working fine, I am getting data to "anotherComponent". But In "anotherComponent" I am using forkJoin. I want to get data from subject only after getting data from forkJoin. I am trying like this:
ngOnInit() {
forkJoin([
this.dataService.getUpgradeAppList(),
this.dataService.getClusterList()
]).subscribe((data: any) => {
console.log("forkJoin :: ngOnInit ::", data);
this.appList = data[0].apps;
this.clusterList = data[1];
});
this.selectedClusterService.selectedClusterName.subscribe(res => {
this.selectedCluster = res;
console.log("this.selectedCluster", this.selectedCluster);
});
}
I have tried ngAfterViewInit
, ngAfterContentChecked
with changeDetection also I try to use setTimeout
, but nothing works. Always I am getting subject data first and then forkJoin data.
How I can get forkJoin first and then subject data?
Any help is appreciated...
First of all, there's no way to guarantee a sequence of getting data in your component as you work with async entities. I would use BehaviorSubject
instead Subject
to guarantee that you receive data from other component.
Your service will be like:
import { Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs';
@Injectable({
providedIn: 'root'
})
export class SelectedClusterService {
constructor() { }
public readonly selectedClusterName = new BehaviorSubject<string | undefined>(undefined);
}
Your component:
ngOnInit() {
forkJoin([
this.dataService.getUpgradeAppList(),
this.dataService.getClusterList()
]).
pipe(
tap((data: any) => {
console.log("forkJoin :: ngOnInit ::", data);
this.appList = data[0].apps;
this.clusterList = data[1];
}),
switchMap(() => this.selectedClusterService.selectedClusterName),
filter(res => res !== undefined)
).subscribe(res => {
this.selectedCluster = res;
console.log("this.selectedCluster", this.selectedCluster);
});
}
In your anotherComponent
you can use the switchMap
operator to start receiving data from oneComponent
and the filter
to ignore initial value in BehaviorSubject
that we set to undefined
.