Home > Net >  Avoid calling function multiple times in angular
Avoid calling function multiple times in angular

Time:12-22

In below snippet, I am calling the same function named isSiteAlreadyAdded(site.id) for 3 different attribute. Is there any way so I can store the value for particular option tag and use it in for given options attribute?

<div >
          <select style="width: 100%;" id="sites" [(ngModel)]="site" name="sites" #sites="ngModel" required>
            <option [ngValue]="null" selected>Select Site</option>
            <option *ngFor="let site of sitesToAdd" [ngValue]="site" data-toggle="tooltip" data-placement="top" title="{{isSiteAlreadyAdded(site.id) ? 'Site is already added.':''}}" [ngClass]="{'alert alert-secondary': isSiteAlreadyAdded(site.id)}" [disabled] = "isSiteAlreadyAdded(site.id)">{{site.name}}</option>
          </select>
      </div>

CodePudding user response:

As described in the linked post from @dan vid, function calls within the template are a bad practice because they will be executed with each change detection tick.

So, either you can use a pipe or you pre-calculates the respective value.

Pipe

If you're using a pipe you'd still calculate the values multiple times but only if the input value of the pipe changes, which reduces the times of re-calculation by a lot compared to function calls in the template.

A basic pipe would look like this:

@Pipe({ name: 'isAlreadyActive' })
export class IsAlreadyActivePipe implements PipeTransform {

  transform(id: string): boolean { // <- or any other return type instead of boolean
    // Implement your check and return the result
  }

}

And the call in your case would look like this:

<option  
  ...
  title="{{ site.id | isAlreadyActive ? 'Site is already added.': '' }}" 
  ...
  >
  {{site.name}}
</option>

You'll find more about pipe here.

Storing a conditional result in a variable

There is also the possibility to store the pipe return value in a variable (see here).

This would look like this:

<ng-container *ngIf="site.id | isAlreadyActive as isActive">
  <option  
    ...
    title="{{ isActive ? 'Site is already added.': '' }}" 
    ...
  >
  {{site.name}}
  </option>
</ng-container>

In this example, we've stored the result in isActive and your calculation would only be executed one time but as soon as the return value is falsy the content of the *ngIf isn't shown.

In you case, for example, you could return instead of a simply boolean and object containing a boolean, e.g., { isActive: returnValue }. That way your return value would be truthy and the content would be shown.

Pre-Calculation

The other option would be to pre-calculate the value in your component and assign the value to site.isActive as example. That way you only have one calculation, which is also better than a function call from the template.

  • Related