2
votes

I am calling one method inside ngFor to get label of input its trigger for 8 times even in ngFor there is 2 item. It should be invoked for two times only. What could be the reason it is getting called for multiple times.

<form [formGroup]="parentForm">
   <div formGroupName="child">
    <ng-container *ngFor="let item of parentForm.get('child').controls | keyvalue; let i = index">
      <div class="form-group">
      <label>{{getLabel(item.key)}} {{i}} </label>
      <input type="text" [formControlName]="item.key">
      </div>
    </ng-container>
   </div>
  </form>   
  getLabel(item) {
     console.log('trigger item') // its get printed in console for 8 times
  if(item == 'data')  { 
    return 'Your Data' 
  } 
  return 'Your Name'
  }

Playground: https://stackblitz.com/edit/angular-ivy-hnaegv?file=src%2Fapp%2Fapp.component.html

2
Angular doesnt work that way, you shouldnt be calling a function fromt he html since its going to be called everytime angular run a change detection. Take a look at this: medium.com/showpad-engineering/… - ukn
Actually there is no way to add label in formControl and add them html, i cant get which way i should follow in order to get rid of multiple calls - Indraraj26

2 Answers

4
votes

As @ukn mentioned in the comment you should not use function calls on template.

getLabel function is executed every time Angular change detection runs.

You can to avoid multiple function calls, Using pipes. let Angular know that execution of a pipe can be skipped safely if the pipe’s input does not change

import { Pipe, PipeTransform } from '@angular/core';

@Pipe({
  name: 'getLabel'
})
export class GetLabelPipe implements PipeTransform {

  transform(value: any, args?: any): any {
         console.log('trigger item')
  if(value == 'data')  { 
    return 'Your Data' 
  } 
  return 'Your Name'
  }

}

Example

1
votes

its better to organize your data using javascript first. then your html should just display the data in the ngFor loop:

var displayItems = [];
parentForm.get('child').controls.forEach(item => {
    item.label = getLabel(item.key);
    displayItems.push(item);
});
this.displayItems = displayItems;

html;

<div *ngFor="let item of displayItems">
  <label>{{item.label}} {{i}} </label>
</div>