20

I am trying to display number format in my angular 4 application. Basically what i am looking at is if the number is in 12.23 millions then it should display For e.g 12.2M (One decimal place)

If the number is 50,000.123 then 50.1K

How do i achieve that in angular. Do I need to write a directive ? Are there any inbuilt pipes in angular ?

structure

export interface NpvResults  {

            captiveInsYear: number[];
            captiveInsPremiumPaid: number[];
            captiveInsTaxDeduction: number[];
            captiveInsLoanToParent: number[];
            captiveInsCapitalContribution: number[];
            captiveDividentDistribution: number[];
            captiveInsTerminalValue: number[];

        }

The array is initialized to the following value

this.sourceResults.captiveInsPremiumPaid = [1,2,3,4,5];

The html

<td *ngFor= "let item of NpvResults.captiveInsPremiumPaid" >{{item}}</td>
br.julien
  • 3,420
  • 2
  • 23
  • 44
Tom
  • 8,175
  • 41
  • 136
  • 267
  • https://stackoverflow.com/questions/2685911/is-there-a-way-to-round-numbers-into-a-reader-friendly-format-e-g-1-1k check here for answer – Karun Feb 02 '18 at 12:57

4 Answers4

59

you can create PIPE

import { Pipe, PipeTransform } from '@angular/core';

@Pipe({
  name: 'thousandSuff'
})
export class ThousandSuffixesPipe implements PipeTransform {

  transform(input: any, args?: any): any {
    var exp, rounded,
      suffixes = ['k', 'M', 'G', 'T', 'P', 'E'];

    if (Number.isNaN(input)) {
      return null;
    }

    if (input < 1000) {
      return input;
    }

    exp = Math.floor(Math.log(input) / Math.log(1000));

    return (input / Math.pow(1000, exp)).toFixed(args) + suffixes[exp - 1];


  }

}

implement in the view

{{ model | thousandSuff  }} <!-- 0 decimals -->

{{ model | thousandSuff : 2  }}  <!-- X decimals -->

result

{{ 22600000 | thousandSuff }} -> 23M

{{ 22600000 | thousandSuff : 2 }} -> 22.60M

mQuiroz
  • 1,339
  • 13
  • 11
  • 2
    it works pefect but if you have 1.565656 and fix the number till 2 decimals with the args argument It perform a round and the result is 1.6, so to get 1.5 you have to do this. return (input / Math.pow(1000, exp)).toFixed(args+1).slice(0, (args*-1)) + suffixes[exp - 1]; – Esteban Perez Apr 08 '19 at 22:41
  • This should be the accepted answer. – alsami Dec 22 '21 at 13:31
3

Here I just give you an idea first create
Html
{{number | shortNumber}}
you can create your own custom pipe filter in which you can pass your number in the pipe and then, you can do code like below, put this logic in your custom pipe.

Pipe filter

getformat(){
    if(number == 0) {
    return 0;
}
else
{        
  // hundreds
  if(number <= 999){
    return number ;
  }
  // thousands
  else if(number >= 1000 && number <= 999999){
    return (number / 1000) + 'K';
  }
  // millions
  else if(number >= 1000000 && number <= 999999999){
    return (number / 1000000) + 'M';
  }
  // billions
  else if(number >= 1000000000 && number <= 999999999999){
    return (number / 1000000000) + 'B';
  }
  else
    return number ;
  }
}

you can do like this.For creating custom pipe you can refer to this siteclick here

Brijesh Mavani
  • 1,070
  • 1
  • 15
  • 23
  • 1
    Its been quite helpful however the numbers could be in negative as well. i.e negative thousand, negative , million and negative billion – Tom Feb 04 '18 at 18:23
  • 1
    This pipe example will handle negative numbers: https://medium.com/@thunderroid/angular-short-number-suffix-pipe-1k-2m-3b-dded4af82fb4 – Giant Elk Sep 04 '19 at 01:10
2

The easiest way is to make a pipe and a service. You can do the actually formatting in service using numeral js library and import that service in the pipe and apply formatting in transform method.

import { Pipe, PipeTransform } from '@angular/core';
import { NumberFormatService } from '../utils/number-format.service';

@Pipe({
  name: 'numberFormat'
})
export class NumberFormatPipe implements PipeTransform {

  constructor(private nF: NumberFormatService) {}

  transform(value: any, args?: any): any {
    if(args == "commas"){
      return this.nF.addCommas(value);
    }
    else if(args == "kmb"){
      return this.nF.addKMB(value);
    }
    return value;
  }

}

import { Injectable } from '@angular/core';
import * as numeral from 'numeral';

@Injectable({
  providedIn: 'root'
})
export class NumberFormatService {

  constructor() { }

  public addCommas(val){
    return numeral(val).format('0,0');
  }

  public addKMB(val){
    return numeral(val).format('0[.]00a');
  }
}

html template file
{{dailyData.avgDaily | numberFormat: 'commas'}}
{{dailyData.avgDaily | numberFormat: 'kmb'}}
  1. You can get numeral js dependency documentation from official site link.
  2. You can install numeraljs in the angular application using npm install numeral --save
ideeps
  • 379
  • 4
  • 15
  • What is the rationale behind creating a service and not doing the numeral.js stuff inside the pipe itself? Does it have anything to do with parallel execution/performance or is it to also make the formatting logic available to Typescript code via the service? – Partho May 18 '19 at 22:03
  • 1
    Pipes are basically meant to be used in the templates. The main reason behind creating a service is just splitting the pipe and the data formatting logic. If you create a service, you can also re-use the service from other components, directives, or service itself. But depends on your requirements, there is no any strict standards that you need to follow and I don't think it will impact anything. – ideeps May 21 '19 at 21:34
0

I write the below pipe, it will handle all of the negative scenarios( Negative numbers, Strings, blank) as well. And works best in all of the cases. Complete Article here.

import { Pipe, PipeTransform } from '@angular/core';

@Pipe({
  name: 'numberSuffix'
})
export class NumberSuffixPipe implements PipeTransform {
  transform(input: any, args?: any): any {
    let exp;
    const suffixes = ['K', 'M', 'B', 'T', 'P', 'E'];
    const isNagtiveValues = input < 0;
    if (Number.isNaN(input) || (input < 1000 && input >= 0) || !this.isNumeric(input) || (input < 0 && input > -1000)) {
      if (!!args && this.isNumeric(input) && !(input < 0) && input != 0) {
        return input.toFixed(args);
      } else {
        return input;
      }
    }

    if (!isNagtiveValues) {
      exp = Math.floor(Math.log(input) / Math.log(1000));

      return (input / Math.pow(1000, exp)).toFixed(args) + suffixes[exp - 1];
    } else {
      input = input * -1;

      exp = Math.floor(Math.log(input) / Math.log(1000));

      return (input * -1 / Math.pow(1000, exp)).toFixed(args) + suffixes[exp - 1];
    }
  }
  isNumeric(value): boolean {
    if (value < 0) value = value * -1;
    if (/^-{0,1}\d+$/.test(value)) {
      return true;
    } else if (/^\d+\.\d+$/.test(value)) {
      return true;
    } else {
      return false;
    }
  }
}
Nimish goel
  • 2,561
  • 6
  • 27
  • 42