Search code examples
angularstylesng-classng-style

How to avoid using function in ngStyle or ngClass?


This is an annoying issue if I can say so ... If I use a method in the template, this will be called so many timesss.... due of the change detection of Angular.

3511 messages (method calls) in just 30 seconds, only for 12 items.

enter image description here

how my code looks initial: html:

<td *ngFor="let value of values"
      class="value">
    <span [ngStyle]="getValueStyle(value)">{{value}}</span>
  </td>

.ts:

getValueStyle(value: any) {
console.log(value);
let stringValue = value.toString();
if (!stringValue.includes('%')) return '';

let index = stringValue.indexOf('%');
let formatedNumber = stringValue.substring(0, index).replace(/\s/g, '');
let numberValue = Number(formatedNumber);
if (Number.isNaN(numberValue) || numberValue == 0) {
  return {'color': '#585858'};
} else if (numberValue > 0) {
  return {'color': '#009900'};
} else if (numberValue < 0) {
  return {'color': '#cc0000'};
}

return '';

}

To avoid using function in template, I declared 3 classes in .scss and made the verification in .html (can do it because is a simple comparison)

<td *ngFor="let value of values"
      class="value">
    <span [ngClass]="!value.includes('%')
      ? 'neutral'
      : value.includes('-')
          ? 'negative'
          : (value == '0')
            ? 'neutral'
            : 'positive'">{{value}}</span>
  </td>

But, if i need to compute a dynamic style, how can avoid these repeatedly calls? Anyway, I don't know if using ngClass is a good solution instead ngStyle, because now, I can not see in console how many times this will be executed. Which is the best way to solve it?


Solution

  • In general you can "map" your array and convert it in an array of objects,e.g.

    const listValues=this.values.map(x=>{
       return {
          value:x,
          style:this.getValueStyle(x)
       }
    })
    

    And use

    <td *ngFor="let item of listValues"
          class="value">
        <span [ngStyle]="item.style">{{item.value}}</span>
      </td>
    

    So, only call to getValueStyle so many times elements there are in your array "values"