Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Async Pipe in Template inside ngFor block triggers http GET calls loop

I have the following component Template:

<div *ngFor="let ctrl of data; trackBy:ctrl?.Id">
   <div *ngIf="getNext(ctrl.nextDate) | async as next">
        <span>{{next | date: 'dd.MM.yyyy'}}</span>
   </div>
</div>

getNext() is a simple method returning an Observable<Date>:

public getNext(deadline: string): Observable<Date> {
   return this.http.get<Date>(`${this.config.apiEndpoint}/api/meeting?deadline=${deadline}`);
}

My goal would be to invoke the method and subscribe to the observable with the async pipe in the template. However when I run the application endless GET and OPTIONS requests are generated.

Also if I place the method call outside the ngFor the same happen. The call would need to be executed inside the ngFor as the parameter is different for each collection item.

Why the method is simply called once and no more calls generated after the subscription?

like image 265
Francesco Avatar asked Feb 15 '18 17:02

Francesco


1 Answers

Calling functions in template is usually not a very good idea as it leads to unpredictable results. This is how you can restructure your code to avoid this:

data: any = [....] // some data
data$: Observable[];

ngOnInit() {
    this.data$ = this.data.map(elem => this.getNext(elem));
} 

public getNext(deadline: string): Observable<Date> {
   return this.http.get<Date>(`${this.config.apiEndpoint}/api/meeting?deadline=${deadline}`);
}

And in your template:

<div *ngFor="let ctrl of data$">
   <div *ngIf="ctrl | async as next">
        <span>{{next | date: 'dd.MM.yyyy'}}</span>
   </div>
</div>

Here's a stackblitz I created where you can see how a similar mechanism works: https://stackblitz.com/edit/angular-nyn4qz

like image 102
Boris Lobanov Avatar answered Oct 12 '22 23:10

Boris Lobanov