Which way has the best performance applying several classes to html tags? Angular 2

785 views Asked by At

I am building a calendar with prices, I have 3 nested elements:

- calendar-layout
-- calendar-month
--- calendar-week

In the calendar-week I have to do several calculations for the different styles that can have each day,

    // Calendar-week Html
    <div [ngClass]="dayClass(date, i)" *ngFor="let date of days; let i = index;"
         (click)="onClick(date)" [class.not-selectable]="isDayNotSelectable(date)">
       <span class="date-number">{{ date |  date:'d'  }}</span>
       <small class="price" *ngIf="calendarInfo.prices"> {{ getPrice(date) }} </small>
    </div>

// Calendar-week Component
  dayClass(date, i) {
    let cssClass = 'day ';
    if (isDateFrom()) return `${cssClass} selected dateFrom`;
    if (isDateTo()) return `${cssClass} selected dateTo`;
    if (isBeetween()) return `${cssClass} between`;
    if (isReccommended()) cssClass += `recommended `;
    if (isNotPrices()) return cssClass;
    let price = this.calendarInfo.prices[date].price
    cssClass += price <= this.minPrice ? 'low' : price >= this.maxPrice ? 'high' : 'normal';
    return cssClass;
  }

As we can see there are a lot of classes that can be placed in the "day" tag. I've seen that my dayClass () function can be distributed using various approaches with the directive [ngClass], but I don't want to use them without knowing which method is really the most effective.

[ngClass]="{'class1':condition1, 'class2': condition2, 'class3':condition3}"
[ngClass.class1]="menu1 || menu2" [ngClass.class2]="(menu1 || menu2) && something">   

Does anyone know what is the most efficient way to apply classes to an HTML tag having multiple calculations?

2

There are 2 answers

2
Aakash Garg On

Create a pure pipe, that way you pipe will not be called until your date changes. That pipe will return a class for that date and will not get called until your date changes. You current approach is not good as your method will be invoked at each re-render.

4
Qortex On

You should always avoid method calls in a template. That's because the rendering engine cannot determine if the function changes value or not given changes in the execution environment variables.

In your example, it cannot know if dayClass changes value if date changes value. Or if another variable changes (dayClass could be unpure and depend on other variables).

Thus, any change detection cycle will require the function to be called, in order to be sure any change in the function value would be caught.

You can witness this behaviour by putting a console.log inside your function, you will see it gets executed a lot of times.

When you use direct dependencies such as ngClass with direct variables, the rendering engine knows when the value changes or not. In your example, that's when condition1 changes value.

If condition1 is variable1 && variable2 for example, the engine will watch for variable1 and variable2 values and trigger an update only when those values change (look for information on ngZone to understand how it is performed).

So you can see it is much more efficient to avoid function calls and always look for direct evaluation.

Then, ngClass or ngClass.my_class should have the same perfs, they just manipulate DOM directly.