移除AngularJS货币过滤器的小数/分位

64

有没有办法从货币过滤器的输出中去除小数点或美分?我正在做这样的事情:

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

这将输出:

$1,000.00

相反,我想要的是:

$1,000

使用货币过滤器可以实现吗?我知道我可以在数字前面添加美元符号,并且我可以编写自己的过滤器,但是我希望使用现有的货币过滤器存在一个简单的方法。

谢谢。


2
很遗憾,货币过滤器使用硬编码格式号码调用,保留2位小数。目前唯一的解决方案是添加自定义过滤器。 - Liviu T.
12个回答

116

更新: 从版本1.3.0开始 - currencyFilter: 添加fractionSize作为可选参数,详见commit和更新的plunker

{{10 | currency:undefined:0}}

注意,它是第二个参数,所以您需要传递未定义来使用当前区域货币符号。

更新:请注意,这仅适用于在数字之前显示的货币符号。 从版本1.2.9开始,它仍然硬编码为2位小数。

这里是一个修改后的版本,它使用了angular的formatNumber的副本,以启用货币的0小数位。


通常情况下,这应该可以在本地定义或currencyFilter调用中进行配置,但现在(1.0.4),它被硬编码为2个小数位。 自定义过滤器:
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) + ')';
    };
  } ]);

模板:

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

示例:

更新: 修复了处理负值时的错误。


@NikhilDabas 我已经修复了,尽管我认为这会将实现与默认货币筛选事件绑定。 - Liviu T.
1
这种方法不适用于货币符号在数字后面的区域设置。 - Ben Lesh
1
@blesh 是的,你说得对,它不会起作用。我会将其作为警告放置。 - Liviu T.
问题在于Angular没有使他们的formatNumber函数可用,因此无法直接用于自定义格式化货币。 - Liviu T.
我认为,如果他们只是添加了一个设置数字精度的选项,那么这个问题也会得到解决。 - Ben Lesh
显示剩余2条评论

32

这个问题似乎很老,给出的答案也很好。然而,还有另一个替代方案也可以帮助解决问题(我在我的项目中使用)。

这种方法非常适用于正负数值前缀和后缀带货币符号的情况。

自定义过滤器:

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}'), '')
        }
    }])

模板:

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

不同区域设置的示例:

  • 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

请参阅实时演示,了解美元丹麦克朗的格式。

更新

请注意,此解决方案适用于AngularJS 1.2和早期版本的库。从AngularJS 1.3开始,可以使用货币格式化程序,并指定第三个参数来指定小数位数 - "要将金额四舍五入到的小数位数"

请注意,为了使用默认的来自AngularJS本地化的货币格式,您必须将货币符号(第二个参数)设置为undefinednull不起作用)。在演示中的示例:美元丹麦克朗


2
非常感谢,我更喜欢这个,因为它使用了原始的 $filter 并且只是“修复”了尾数小数。 - stackular
这是正确的答案,因为它适用于所有当前的语言环境...例如瑞士法语,其货币符号在数字之后。 - Ben Lesh
注意:这里有一个小错误:如果小数分隔符是“.”或任何其他“特殊”的正则表达式字符,则需要在RegExp字符串中进行转义。 - Ben Lesh
@blesh,感谢您的评论。如果您查看正则表达式new RegExp('\\' + formats.DECIMAL_SEP + '\\d{2}'),第一个\\字符会被转换为转义字符。因此,在使用.+作为分隔符的情况下,您将得到类似于/\.\d{2}//\+\d{2}/的正则表达式。 - Tom
如果小数点分隔符是“d”,那么这将导致错误。 - Ben Lesh
1
@blesh,啊是的,在d的情况下,这种机制是行不通的(d将变成\d,只匹配数字,而不是字母d)。然而,这个建议是基于一个假设:Angularformat.DECIMAL_SEP在所有可用的Angular文化中仅限于少数字符(例如,.)。但是,如果您使用自定义文化,例如使用d作为DECIMAL_SEP,那么该机制将无法按预期工作。谢谢。 - Tom

31

另一个值得考虑的问题是,如果您知道只有一个语言环境或一种货币类型,那么可以将货币符号放在数字前面,然后像这样使用数字过滤器(用于美元货币)。

  ${{Price | number:0}}

如果您不想更换新的过滤器,且只需使用一种货币,则此解决方案更像是一个快速修复。


2
这种方法的一个缺点是负数会打印为$-100而不是$(100)。 - Andrew Thomas
这并不完全回答了问题,但它解决了我的问题。 - Dr. Hilarius

19

虽然已经很晚了,但或许这能帮到某个人

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

那么让我们看一些带有输出的例子。

{{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

查看演示


5

这是另一种类似的解决方案,但它会去除10.00中的小数位,但保留其他任何小数位。

$10.00 变为 $10

$10.20 保持不变为 $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;
    };
}]);

4

如果您使用的是Angular版本<1.3,且需要进行i18n处理,则最简单的方法是:

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

这样做可以根据语言环境正确使用分隔符和货币符号来格式化数字。

3

另一种解决方案是去除小数点后的零,并为最常见的货币找到正确的货币符号:

{{10.00|money:USD}} 变成 $10

{{10.00|money:EUR}} 变成 €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, '');
};
} ]);

2
如果您使用angular-i18nbower install angular-i18n),您可以使用修饰符更改语言环境文件中的默认值,例如:
$provide.decorator('$locale', ['$delegate',
  function ($delegate) {
    $delegate.NUMBER_FORMATS.PATTERNS[1].maxFrac = 0;
    $delegate.NUMBER_FORMATS.PATTERNS[1].minFrac = 0;
    return $delegate;
}]);

请注意,这将适用于您代码中所有货币筛选器的使用。

2

如果你想将数字四舍五入到最接近的1000美元,可以参考以下链接:演示

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) {

});

2

我稍微修改了@Liviu T.发布的过滤器,可以接受带符号的货币和特定数量的小数:

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;
  };
} ]);

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

输出:

$10
$10.56

Demo


负数似乎无法正常工作。最后一个“)”被移除了。 - Billy McKee

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接