Issue
I’m using declarative RxJS to return a response object from my back-end service. I am able to grab the data in my bay-page.ts
file and display it in my html. However, I want the data to be displayed in my results-page.ts
file. I grab the user inputs using Subjects and pass them in a method in my bay-page.ts
file, that will then fire off the HTTP request.
But, how do I grab those results and display them in my results-page.html
file?
bay-service.ts
file:
private bayStartSelectedSubject = new Subject<number>();
bayStartSelectedAction$ = this.bayStartSelectedSubject.asObservable();
private bayEndSelectedSubject = new Subject<number>();
bayEndSelectedAction$ = this.bayEndSelectedSubject.asObservable();
selectedBayChanged(selectedBayStartNumber: number, selectedBayEndNumber?: number): void {
this.bayStartSelectedSubject.next(selectedBayStartNumber);
this.bayEndSelectedSubject.next(selectedBayEndNumber);
}
grabHuResponsePOST$ = combineLatest([
this.bayStartSelectedAction$,
this.bayEndSelectedAction$
])
.pipe(
switchMap(([bayStart, bayEnd]) => {
if (bayEnd == null || bayEnd <= 0) {
bayEnd = bayStart;
}
let huRequest: HuRequest = {
"centerId": "COS",
"beginBayId": bayStart,
"endBayId": bayEnd
}
const headers = new HttpHeaders({
'Content-Type': 'application/json'
});
let options = {
headers: headers
}
// this.invalidBay.next(true);
return this.httpClient.post<HuResponse>(this.HandlingUnitResponseUrl, huRequest, options);
}),
tap(showDataPlease => console.log('Bays: ', JSON.stringify(showDataPlease))),
);
bay-page.ts
file:
ngOnInit() {
this.bayForm = new FormGroup({
'bayStart': new FormControl(null, [Validators.required]),
'bayEnd': new FormControl(null, [Validators.required])
});
this.bayService.invalidBay$.subscribe(
value => {
console.log(value);
this.invalidBay = value;
}
);
this.bayService.grabHuResponsePOST$.subscribe(p => {
});
}
onSubmit() {
this.bayService.selectedBayChanged(this.bayForm.get('bayStart').value, this.bayForm.get('bayEnd').value);
this.navCtrl.navigateForward([`/results/`]);
}
results-page.ts
file:
bayOrBays$ = this.bayService.grabHuResponsePOST$
.pipe(
map(response => response.bays),
catchError(err => {
this.errorMessageSubject.next(err);
return EMPTY;
}),
tap(showDataPlease => console.log('Bays: ', JSON.stringify(showDataPlease)))
);
results-page.html
file:
<ion-card *ngFor="let bay of bayOrBays$ | async; index as i"
class="ion-no-margin">
<ion-card-header>
<ion-card-title>Bay {{ bay.bayCode }}</ion-card-title>
<ion-card-subtitle>{{ bay.shipments.length }} Shipments</ion-card-subtitle>
</ion-card-header>
</ion-card>
I am obviously missing something with a subscription because this doesn’t work in my results-page.ts
file, but it DOES work, if I put it in my bay-page.ts
file.
Solution
In general, late subscribers will not receive previously emitted values. You can use the shareReplay
operator to emit prior values to new subscribers upon subscription:
grabHuResponsePOST$ = combineLatest([
this.bayStartSelectedAction$,
this.bayEndSelectedAction$
])
.pipe(
switchMap(([bayStart, bayEnd]) => {
if (bayEnd == null || bayEnd <= 0) {
bayEnd = bayStart;
}
let huRequest: HuRequest = {
"centerId": "COS",
"beginBayId": bayStart,
"endBayId": bayEnd
}
const headers = new HttpHeaders({
'Content-Type': 'application/json'
});
let options = {
headers: headers
}
// this.invalidBay.next(true);
return this.httpClient.post<HuResponse>(this.HandlingUnitResponseUrl, huRequest, options);
}),
tap(showDataPlease => console.log('Bays: ', JSON.stringify(showDataPlease))),
shareReplay(1) // <-----
);