Skip to content
Advertisement

Angular – function in ngFor called multiple times

I have a template:

<mat-card *ngFor="let cargo of cargos" class="cont-mat">
...  
 <mat-checkbox *ngFor="let truck of (getTrucksByUserIdAndRules(cargo.id) | async)" formControlName="truckId">{{truck.regNumber}}</mat-checkbox>

Component

getTrucksByUserIdAndRules(cargoId: string) {
    return this.cargosService.getTrucksByUserIdAndRules(this.userId, cargoId).pipe(
      map(response => {
        console.log(response.trucks);
       return response.trucks;
      })
    )
  }

and service:

getTrucksByUserIdAndRules(userId: string, cargoId: string): Observable<any> {
    const url = BACKEND_URL_2 + "getTrucksByUserIdAndRules/" + userId + "/" + cargoId;
    return this.http.get(url).pipe(
     map(response => {
      return response;
     })
  );
  }

I want to fetch the list of trucks in my template based on a parameter cargo.id. I’m getting data from backend but the function getTrucksByUserIdAndRules(cargo.id) is called multiple times. I know this is not a good practise to use functions inside template and any other solution will be welcome.

Advertisement

Answer

In your constructor/ngOnInit component, load all the data. Note that you should do that in a resolver, it will be processed before the component is shown on your browser. You can check out more about resolver here.

trucksByCargoId: Map<number, Trucks>;

constructor(private yourService: YourService) {
 this.trucksByCargoId = new Map();
 this.cargos.forEach(cargo => {
     // note that I dont recommand making HTTP call inside a loop, you should make only one HTTP call for all the cargo
     this.yourService.getTrucksByUserIdAndRules(cargo.id).subscribe(result => { 
       trucksByCargoId.set(cargo.id, result);
     });
 }
}

and in your HTML template, retrieve the trucks corresponding to the cargo with the Map you created in your component

<mat-card *ngFor="let cargo of cargos" class="cont-mat">
...  
 <mat-checkbox *ngFor="let truck of trucksByCargoId.get(cargo.id)" formControlName="truckId">{{truck.regNumber}}</mat-checkbox>
User contributions licensed under: CC BY-SA
7 People found this is helpful
Advertisement