Removing AngularJS currency filter decimal/cents
Asked Answered
S

12

63

Is there a way to remove the decimal/cents from the output of a currency filter? I'm doing something like this:

<div>{{Price | currency}}</div>

Which outputs:

$1,000.00

Instead, I'd like:

$1,000

Can that be done using the currency filter? I know I can prepend a dollar sign onto a number, and I could write my own filter, but I was hoping a simple method exists with the existing currency filter.

Thank you.

Spiderwort answered 8/2, 2013 at 22:33 Comment(1)
Unfortunately no. The currency filter uses a hardcoded format number call using 2 decimal places. The only solution so far is to add a custom filterCathrinecathryn
C
114

Update: as of version 1.3.0 - currencyFilter: add fractionSize as optional parameter, see commit and updated plunker

{{10 | currency:undefined:0}}

Note that it's the second parameter so you need to pass in undefined to use the current locale currency symbol

Update: Take note that this only works for currency symbols that are displayed before the number. As of version 1.2.9 it's still hardcoded to 2 decimal places.

Here is a modified version that uses a copy of angular's formatNumber to enable 0 fractionSize for currency.


Normally this should be configurable either in the locale definition or the currencyFilter call but right now(1.0.4) it's hardcoded to 2 decimal places.

Custom filter:

myModule.filter('noFractionCurrency',
  [ '$filter', '$locale',
  function(filter, locale) {
    var currencyFilter = filter('currency');
    var formats = locale.NUMBER_FORMATS;
    return function(amount, currencySymbol) {
      var value = currencyFilter(amount, currencySymbol);
      var sep = value.indexOf(formats.DECIMAL_SEP);
      if(amount >= 0) { 
        return value.substring(0, sep);
      }
      return value.substring(0, sep) + ')';
    };
  } ]);

Template:

<div>{{Price | noFractionCurrency}}</div>

Example:

Update: fixed a bug when handling negative values

Cathrinecathryn answered 9/2, 2013 at 11:7 Comment(7)
This fails with negative values. {{ -1 | currency }} = ($1.00) but {{ -1 | noFractionCurrency }} = ($1J
@NikhilDabas Fixed it, though I think this couple the implementation to the default currency filter event moreCathrinecathryn
This won't work for locales where the currency symbol comes after the number.Trinl
@blesh Yes you're right it won't work. I'll put it as a warning.Cathrinecathryn
@blesh The problem is that angular doesn't make their formatNumber function available so that it can be used directly to custom format a currency.Cathrinecathryn
Well I think if they just added an option to set the precision of the number it would solve the problem as well.Trinl
This is a plug and play custom filterOsteo
H
31

The question seems to be pretty old and the given answers are nice. However, there is another alternative solution which can also help (which I use in my projects).

This is working very well with currency symbols prefixing as well as suffixing the number for positive and negative values.

Custom filter:

angular.module('your-module', [])
    .filter('nfcurrency', [ '$filter', '$locale', function ($filter, $locale) {
        var currency = $filter('currency'), formats = $locale.NUMBER_FORMATS;
        return function (amount, symbol) {
            var value = currency(amount, symbol);
            return value.replace(new RegExp('\\' + formats.DECIMAL_SEP + '\\d{2}'), '')
        }
    }])

Template:

<div>{{yourPrice| nfcurrency}}</div>

Examples for different locales:

  • 10.00 (en-gb) -> £10
  • 20.00 (en-us) -> $20
  • -10.00 (en-us) -> ($10)
  • 30.00 (da-dk) -> 30 kr
  • -30.00 (da-dk) -> -30 kr

Please have a look at live demo for US dollars and Danish Krone.

Update

Please note that this workaround is good for AngularJS 1.2 and earlier releases of the library. As of AngularJS 1.3 you can use currency formatter with third parameter specifying fraction size - "Number of decimal places to round the amount to".

Note that in order to use default currency format coming from AngularJS localization, you would have to use currency symbol (second parameter) set to undefined (null or empty will NOT work). Example in demos for US dollars and Danish Krone.

Haloid answered 8/7, 2013 at 21:0 Comment(6)
Thanks a lot, I prefer this one because it uses the original $filter and only "fixes" the trailing decimals.Gaut
This is the correct answer, as it will work with all current locales... such as French Swiss, which has the currency after the number.Trinl
NOTE: There's a minor bug with this: If the decimal seperator is a '.', or any other "special" regexp character, it will need to be escaped in the RegExp string.Trinl
@blesh, thank you for your comment. If you look at that regular expressions new RegExp('\\' + formats.DECIMAL_SEP + '\\d{2}'), the first \` characters are converted to the escape character. So in case of .` or even + as a separators, you would get regular expressions like:/\.\d{2}/ or /\+\d{2}/ respectively.Haloid
if the decimal seperator is a "d" for some reason, this will break.Trinl
@blesh, ah yes, in case of d the mechanism will not work (d would become \d and would match digits only, not letter d). However, the proposition was made with an assumption that Angular format.DECIMAL_SEP is limited to a few characters (e.g. ,, .) only across all available Angular cultures. But if you would use a custom culture, which for instance used d as a DECIMAL_SEP then that mechanism wouldn't work as expected. ThanksHaloid
D
31

Another thing that is worth considering is if you know you only have one locale or one type of currency, you could put the currency symbol before the number and then use the number filter like so (for US currency).

  ${{Price | number:0}}

More of a quick fix solution if you don't want to throw in a new filter and only have one currency.

David answered 18/12, 2013 at 16:30 Comment(2)
one downside to this approach is that negative numbers print as $-100 rather than $(100)Potentate
This doesn't totally answer the question, but it solves my problem.Maidamaidan
S
19

It's late but might be it can help some one

{{value | currency : 'Your Symbol' : decimal points}}

So let's see some examples with output

{{10000 | currency : "" : 0}}           // 10,000
{{10000 | currency : '$' : 0}}          // $10,000 
{{10000 | currency : '$' : 2}}          // $10,000.00 
{{10000 | currency : 'Rs.' : 2}}        // Rs.10,000.00
{{10000 | currency : 'USD $' : 2}}      // USD $10,000.00
{{10000 | currency : '#' : 3}}          // #10,000.000
{{10000 | currency : 'ANYTHING: ' : 5}} // ANYTHING: 10,000.00000

See the demo

Struthious answered 12/4, 2016 at 18:15 Comment(0)
A
5

This is another similar solution, but it removes .00 decimal, but leaves any other decimal amount.

$10.00 to $10

$10.20 to $10.20

app.filter('noFractionCurrency', [ '$filter', '$locale', function(filter, locale) {
    var currencyFilter = filter('currency');
    var formats = locale.NUMBER_FORMATS;
    return function(amount, currencySymbol) {
        amount = amount ? (amount*1).toFixed(2) : 0.00;
        var value = currencyFilter(amount, currencySymbol);
        // split into parts
        var parts = value.split(formats.DECIMAL_SEP);
        var dollar = parts[0];
        var cents = parts[1] || '00';
            cents = cents.substring(0,2)=='00' ? cents.substring(2) : '.'+cents; // remove "00" cent amount
        return dollar + cents;
    };
}]);
Aloe answered 25/5, 2014 at 0:51 Comment(0)
R
4

Solution for angular version < 1.3, if you use i18n the simplest way is:

$filter('number')(x,0) + ' ' +$locale.NUMBER_FORMATS.CURRENCY_SYM;

This way you have the number formatted with correct separators and currency symbol based on locale.

Reyna answered 6/11, 2014 at 10:15 Comment(0)
E
3

Another solution, this one removes the trailing zeros and finds the proper currency symbol for the most common currencies:

{{10.00|money:USD}} to $10

{{10.00|money:EUR}} to €10

/**
 * @ngdoc filter
 * @name money
 * @kind function
 *
 * @description
 * Formats a number as a currency (ie $1,234.56), removing trailing zeros and using the     real currency symbol when possible. When no currency symbol is provided, default
 * symbol for current locale is used.
 *
 * @param {number} amount Input to filter.
 * @param {string=} symbol Currency symbol or identifier to be displayed.
 * @returns {string} Formatted number. *
 */
app.filter('money', [ '$filter', '$locale', function (filter, locale) {
var currencyFilter = filter('currency');
var formats = locale.NUMBER_FORMATS;

var getCurrencySymbol = function (code) {
    switch (code.toUpperCase()) {
        case 'EUR': //Euro
            return '€';

        case 'USD': //Dólar americano
        case 'MXN': //Peso mejicano
        case 'CAD': //Dólar de Canadá
        case 'AUD': //Dólar australiano
        case 'NZD': //Dólar neozelandés
        case 'HKD': //Dólar de Hong Kong
        case 'SGD': //Dólar de Singapur
        case 'ARS': //Peso argentino
            return '$';

        case 'CNY': //Yuan chino
        case 'JPY': //Yen japonés
            return '¥';

        case 'GBP': //Libra esterlina
        case 'GIP': //Libras de Gibraltar
            return '£';

        case 'BRL': //Real brasileño
            return 'R$';

        case 'INR': //Rupia india
            return 'Rp';

        case 'CHF': //Franco suizo
            return 'Fr';

        case 'SEK': //Corona sueca
        case 'NOK': //Corona noruega
            return 'kr';

        case 'KPW': //Won de Corea del Norte
        case 'KRW': //Won de Corea del Sur
            return '₩';

        default:
            return code;
    }
};

return function (amount, currency) {
    var value;
    if (currency) {
        value = currencyFilter(amount, getCurrencySymbol(currency));
    }
    else {
        value = currencyFilter(amount);
    }

    //Remove trailing zeros
    var regex = new RegExp("\\" + formats.DECIMAL_SEP + "0+", "i");
    return value.replace(regex, '');
};
} ]);
Emaciation answered 1/7, 2014 at 19:47 Comment(0)
K
2

And here if you want to round up to nearest $1000: Live Demo:

var app = angular.module('angularjs-starter', []);

app.filter('noFractionRoundUpCurrency',
    [ '$filter', '$locale', function(filter, locale) {
      var currencyFilter = filter('currency');
      var formats = locale.NUMBER_FORMATS;
      return function(amount, currencySymbol) {
        var value = currencyFilter(amount, currencySymbol);
        var sep = value.indexOf(formats.DECIMAL_SEP);
        if(amount >= 0) { 
                    if (amount % 1000 < 500){
                        return '$' + (amount - (amount % 500));
                    } else {
                        return '$' + (amount - (amount % 500) + 500);          
                    }

        }
        else{
                    if (-amount % 1000 < 500){
                        return '($' + (-amount - (-amount % 500)) + ')';
                    } else {
                        return '($' + (-amount - (-amount % 500) + 500)+ ')';          
                    }
        }
      };
    } ]);

app.controller('MainCtrl', function($scope) {

});
Karyolymph answered 21/6, 2013 at 7:8 Comment(0)
Y
2

Exactly what I needed!

I added a conditional to just replace Angular's currency filter altogether and just use a modified version of the filter seen above by @Tom. I'm sure there are better ways to do this but it seems to work well for me thus far.


'use strict';
angular.module('your-module')
  .filter('nfcurrency', [ '$filter', '$locale', function ($filter, $locale) {
    var currency = $filter('currency'), formats = $locale.NUMBER_FORMATS;
    return function (amount, symbol) {
      var value = currency(amount, symbol), valArr = value.split(formats.DECIMAL_SEP);
      if(parseInt(valArr[(valArr.length - 1)]) > 0) {
        return value;
      } else {
        return value.replace(new RegExp('\' + formats.DECIMAL_SEP + '\d{2}'), '');
      }
    };
  }]);
Yakka answered 1/5, 2014 at 14:35 Comment(0)
N
2

I have modified a bit the filter posted by @Liviu T. to accept currencies with symbol after the number and certain number of decimals:

app.filter('noFractionCurrency',
[ '$filter', '$locale', function(filter, locale) {
  var currencyFilter = filter('currency');
  var formats = locale.NUMBER_FORMATS;
  return function(amount, num, currencySymbol) {
    if (num===0) num = -1;
    var value = currencyFilter(amount, currencySymbol);
    var sep = value.indexOf(formats.DECIMAL_SEP)+1;
    var symbol = '';
    if (sep<value.indexOf(formats.CURRENCY_SYM)) symbol = ' '+formats.CURRENCY_SYM;
    return value.substring(0, sep+num)+symbol;
  };
} ]);

For example:

{{10.234 | noFractionCurrency:0}}
{{10.55555 | noFractionCurrency:2}}

Outputs:

$10
$10.56

Demo

Nylons answered 15/7, 2014 at 10:14 Comment(1)
Negative numbers don't seem to work. The last ")" is removed.Heft
P
2

If you'd use angular-i18n (bower install angular-i18n), you could use a decorator to change the defaults in the locale files, like so:

$provide.decorator('$locale', ['$delegate',
  function ($delegate) {
    $delegate.NUMBER_FORMATS.PATTERNS[1].maxFrac = 0;
    $delegate.NUMBER_FORMATS.PATTERNS[1].minFrac = 0;
    return $delegate;
}]);

Note that this would apply to all currency filter uses in your code.

Pierrepierrepont answered 3/2, 2015 at 15:52 Comment(0)
H
0

In Angular 4+

{{totalCost | currency : 'USD' : 'symbol' : '1.0-0' }}
Hardhearted answered 19/9, 2018 at 21:6 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.