Reputation: 43
i have 2 functions
loadItems(): void {
this.service.query().subscribe((res: HttpResponse<Item[]>) =>
(this.items = res.body || []));
}
loadAuditByItem(item: Item) {
this.service.auditByItem(item.id!).subscribe((res: HttpResponse<ItemAudit[]>) =>
(this.auditByItem = res.body || []));
}
i want to display informations from both loadItems() and loadAuditByItem() at the same page i managed to display the name and description from loadItems() but i need to display "createdBy" from loadAuditByItem(item)
<div *ngFor="let item of items">
<div *ngIf="loadAuditByItem(item)">
<span>Name: {{ item.name}}</span>
<span>Description : {{ item.description }}</span>
<span>Created by: {{ auditByItem .createdBy}}</span>
</div>
</div>
Upvotes: 0
Views: 1201
Reputation: 495
Having a function call in ngIf
is very bad for performance (you could add a console.log
and check your console to see how many times it is been called) instead you could use Pipes, that had been said let me give you a solution for your use case:
import { forkJoin, Observable, of, Subject } from "rxjs";
import { map, switchMap } from "rxjs/operators";
...
public items$: Observable<Item[]>;
...
loadItems(): void {
// please consider to edit your backend API to return all data in one API call
// since this nested calls will lead to N+1 calls problem.
this.items$ = this.service.query().pipe(
map((res: HttpResponse<[]>) => res.body || []),
switchMap((items: []) => {
if (items.length === 0) {
return of([]);
}
return forkJoin(
items.map((item: any) =>
this.service.auditByItem(item.id).pipe(
map(audit => {
item.audit = audit;
return item;
})
)
)
);
})
);
}
<div *ngFor="let item of (items$ | async)">
<div>
<span>Name: {{ item.name}}</span>
<span>Description : {{ item.description }}</span>
<span>Created by: {{ item.audit.createdBy}}</span>
</div>
</div>
Bonus:
It is not good to expose HttpResponse
from the service, and it is better to return only the Item[]
and encapsulate the HttpResponse
there.
Upvotes: 1
Reputation: 1093
I would have return the Observable so that *ngIf handle the subscription with the AsyncPipe.
public loadAuditByItem(item: Item): Observable<any> {
return this.service.auditByItem(item.id!);
}
<div *ngFor="let item of items">
<div *ngIf="loadAuditByItem(item) | async as audit">
<span>Name: {{ item.name }}</span>
<span>Description : {{ item.description }}</span>
<span>Created by: {{ audit.createdBy }}</span>
</div>
</div>
Upvotes: 1