Angular 2: pass function to ngClass tag in template

I have worked a bit on this, but have not stumbled upon everything that works.

When I pass the ngStyle function, I get the following error:

Expression 'getClass()' in ProductView has changed after it was checked.

My template looks like this:

 <div class="itemContainer"> <div class="well imageHolder" [ngClass]="getClass()"> <img [src]="'img/thumbs/' + item.images[0]" class="productImage" id="productImage"> </div> </div> 

I am not sure what to fix this or even if it can be done now. I noticed that this error also occurs with ngStyle.

All help would be appreciated.

+5
source share
3 answers

Property binding uses the following syntax: [someProperty]="an Angular template expression" .

In your case, the template expression is a function (rather than, say, a component property). It's great. But according to the Expression Guidelines section of the Template Syntax manual, expressions should be "idempotent." This means that if

expression returns a string or number; it returns the same string or number when called twice in a string. If the expression returns an object (including Date or Array ), it returns the same object reference when called twice in a string.

Since you did not provide code for your getClass() function, we just assume that it violates the idempotent rule. (You probably return a new array or new object each time.)

In development mode (which is the default mode), change detection is performed twice, and it will break idempotent violations.

To fix this, return the same array or object reference (but you can change the contents of the array or object properties / values). For instance.

 export class MyComponent { anArray = []; getClass() { // manipulate (don't reassign) anArray here, and return it return this.anArray; } } 
+7
source

The answer is simple, you can do it with a function, just make sure the function returns the class name

on html:

 <div [ngClass]="getClassByValue('a')"> My Div</div> 

in the ts file:

  getClassByValue(value: string) { switch (value) { case "a": return "class-a"; case "b": return "class-b"; } } 

will end with the class name "class-a" in your element.

Hope this helps :)

+1
source

You should not do this (yes, that probably worked in angular 1.x :)) The check is done if you did not enable production mode:

https://angular.io/docs/js/latest/api/core/enableProdMode-function.html

My assumption (disclaimer: this is a hunch ...) is that you should set literals / variables that reflect the correct state. The variable does not cause side effects where the method may be. I think they provide this because it helps you prevent too frequent digest cycles.

So this is the way:

 <div class="itemContainer"> <div class="well imageHolder" [ngClass]="{ 'classA': variableA, 'classB': variableB }"> <img [src]="'img/thumbs/' + item.images[0]" class="productImage" id="productImage"> </div> </div> 

Therefore, instead of running some code in each digest cycle, which checks whether the class should be installed (and possibly calling new digest cycles, changing other things), you should set these variables when they should be set.

0
source

Source: https://habr.com/ru/post/1241603/


All Articles