In my Angular app, I route to a component. Inside that component, I want to display an item$ observable.
Now, if my service has a cached item, use that, and regardless, request an item from the backend. So the experience might be to show the cached item for a moment, then the backend item replaces it after it loads. If the item doesn't exist on the backend, the cached item would be the only emitted value. If it's not, we show a not found.
Here's how I have tried to execute this:
ngOnInit() {
this.item$ = this.route.paramMap.pipe(
switchMap((params: ParamMap) => {
this.id = params.get('id'); // get the id
if (this.service.item && this.id === this.service.item.id) {
return of(this.service.item); // cached item
}
return of(null); // nothing cached
}),
merge(this.backend.getItem(this.id)) // get backend item
);
}
my template code
<div *ngIf="item$ | async as item; else showNotFound">
<p>{{ item.name }}</p>
<!-- other props omitted -->
</div>
<ng-template #showNotFound>
<p>Not found</p>
</ng-template>
However, merge fires before switchMap and cannot get the item because this.id is not yet set. If I move the merge in front of switchMap, switchMap can't get the param. How can this be done?