4

I'm using ngx-pipe's percentage pipe twice in a label. Once to determine which color class (success or info) and once to display the percentage.

<label class="label" [ngClass]="(item.amount |
percentage:item.total) >= 100 ? 'label-success' : 'label-info'">Progress {{item.amount | percentage:item.total:true}}%</label>

Is there a way that I can store the result of that pipe as a local template variable only once like

<label class="label" #percent="(item.amount |
percentage:item.total)" [ngClass]="percent >= 100 ? 'label-success' : 'label-info'">Progress {{percent}}%</label>

I know you can store it inside an *ngIf or *ngFor directive like

<div *ngIf="item$ | async as item">

or

<div *ngIf="item$ | async; let item">

Is there a similar approach to my issue?

Han Che
  • 8,239
  • 19
  • 70
  • 116
  • why do you need another way if ng-container will not add extra html ? – Muhammed Albarmavi Nov 09 '18 at 13:47
  • Well you gave yourself the answer for a template-oriented solution. Otherwise, know that pipes are simply class instances. This means you can create an instance of them in your component's logic. I am redirecting you to one of my previous answers about a similar question about the date pipe : https://stackoverflow.com/questions/48183677/how-to-format-date-in-component-of-angular-5/48183927#48183927. –  Nov 09 '18 at 13:47
  • @trichetriche is it possible to use async pipe like in your answer of the date pipe ?? – Muhammed Albarmavi Nov 09 '18 at 13:56
  • @malbarmawi yes, [the source code of the pipe](https://github.com/angular/angular/blob/7.0.3/packages/common/src/pipes/async_pipe.ts#L42-L146) only requires a change detector reference. But I wouldn't use it, myslef, I prefer to use RxJS by hand and reserve my async pipes to my templates ! –  Nov 09 '18 at 14:21

1 Answers1

1

AFAIK it isn't possible write now to alias the calculated binding on runtime(*ngFor with pipe is exception), but what you can do is. Create a function/Pure pipe and apply memoization to that function so that computation will less in amount.

<label class="label" 
  [ngClass]="getPercentage(item) >= 100 ? 'label-success' : 'label-info'">
     Progress {{getPercentage(item)}}%
</label>

Component

calculation: any = {};
percentage = new PercentPipe();
// below function can be stay as pure Pipe as well.
getPercentage (item) {
   let key = `${item.amount}-${item.total}`
   if(!calculate[key]) calculate[key] = percentage.transform(item.amount, item.total, true);
   return calculate[key];
}

By this solution we were calculating value once and using it elsewhere. But not in template variable, but memoizing last calculated value in component.

Pankaj Parkar
  • 134,766
  • 23
  • 234
  • 299