I have an observable that is getting customer info and I want then to use the customer number to look up the name
I need this.workDetail$ to contain both responses from getWorkItem which is a JSON object that may contain a customer number, if it does I want to look it up and add the customer name to the observable output
this.workDetail$ = this.workService
.getWorkItem(workNumber)
.pipe(
iif((res: WorkItemNumberResposne) => res.customerNumber),
//want this customer number added to main output stream
this.customerService.getCustomerById(res.customerNumber),
//else nothing to do
);
if iif even the right way to do this?
CodePudding user response:
We could use switchMap
https://www.learnrxjs.io/learn-rxjs/operators/transformation/switchmap operator to take value res
from this.workService.getWorkItem(workNumber)
and then switch to this.customerService.getCustomerById(res.customerNumber)
which will be returned instead. We use iif()
https://www.learnrxjs.io/learn-rxjs/operators/conditional/iif operator to compare, that res?.customerNumber != null || undefined
and based on this condition we will return either trueResult
or falseResult
.
<p>Async Object</p>
<div *ngFor="let item of workDetail$ | async | keyvalue">
{{ item.key }}:{{ item.value }}
</div>
<!--
id:1
item:something
name:Amber
-->
detail = { id: 123, customerNumber: 1 };
person = { id: 1, name: 'Amber', item: 'something' };
workDetail$: Observable<any> = of(this.detail).pipe(
switchMap((res) =>
iif(() => res?.customerNumber != null || undefined, of(this.person), of(null))
),
delay(1000)
);
Feel free to make substitutions yourself and remove the delay.
Working example: https://stackblitz.com/edit/angular-ivy-8b33tr?file=src/app/app.component.ts
CodePudding user response:
iif return an observable or another one according to a condition. Your condition is about the response to an observable so we need use swichMap (you switch the observable "workDetail" to the observable "iif")
If condition is fullfilled you return the observable "this.customerService.getCustomerById(res.customerNumber)", but you transform (using map) to return an object with the properties of the fisrt observable plus the properties of this last Observable (for this I use spread operator, if only want to add a new property you can use some like {...res,customerName:customer.name}
In code
workDetail$: Observable<any> = this.customerService.workDetail$.pipe(
//we don't want this observable else the observable "iif"
switchMap((res:any) =>
iif(() => res.customerNumber,
//if res.customerNumber, return the observable "getCustomerById"
this.customerService.getCustomerById(res.customerNumber).pipe(
//but "transformed"
map((customer:any)=>({...res,...customer}))),
//else simply return an observable using "of"
of(res))
)
);