How Can I Check isNaN in Angular2 Expression?
You can expose the function as a property of the class:
class MyComponent {
isNaN: Function = Number.isNaN;
}
<div>dividerColor="{{isNaN(+price) ? 'warn' : 'primary'}}"</div>
Instead of exposing the isNan function in the component and to apply some rule in the template, I think that it would be a better choice to expose a property having a business meaning. For example :
class MyComp {
hasPrice: boolean;
someAction() {
...
this.hasPrice = !isNaN(this.item.price);
}
}
<div dividerColor="{{hasPrice ? 'warn' : 'primary'}}"></div>
Other answers are not the best way to do it
Other answers suggests to create a component function to check whether the value is NaN like:
*ngIf="myCustomIsNaN(value)"
This approach is, as far as I know, a problem in Angular because you're calling a function to check the value. So the change detector will continue to call that function to check if the value returned changed. If you put a console.log in that function you'll see it is called 1 to 10 times a second thus re rendering the template.
I think the only good way to do this is to use a custom Pipe.
Why is the Pipe a better solution
Consider the following template code:
<div *ngIf="value | isNan"> ... </div>
In this case the change detector trigger a re rendering only if value
changes. And then it evaluates the ngIf
statement and re renders the template accordingly.
Less calls, less renderings, less cpu utilization, more performance. :)
The Pipe code
For elegance in templates I created two pipes to check NaNs: isNaN
and isNotNaN
import { Pipe, PipeTransform } from '@angular/core';
/**
* Pipe to return true if the number is NaN
*/
@Pipe({
name: 'isNaN'
})
export class IsNaNPipe implements PipeTransform {
transform(item: number): boolean {
return isNaN(item);
}
}
/**
* Pipe to return true if the number is NOT NaN
*/
@Pipe({
name: 'isNotNaN'
})
export class IsNotNaNPipe implements PipeTransform {
transform(item: number): boolean {
return !isNaN(item);
}
}
This happens because the expressions are evaluated against view context, not with eval
, JS globals are unavailable in templates.
Considering that Number.isNaN
was polyfilled, technically it can be done with
{{ (+price).constructor.isNaN(+price) ... }}
Though it can be considered a hack. I would suggest to expose each and every helper function as either class property or a pipe.