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.

Tags:

Angular