ChatGPT解决这个技术问题 Extra ChatGPT

How do I format currencies in a Vue component?

My Vue component is like this :

<template>
    <div>
        <div class="panel-group"v-for="item in list">
            <div class="col-md-8">
                <small>
                   Total: <b>{{ item.total }}</b>
                </small>
            </div>
        </div>
    </div>
</template>

<script>
    export default {
        ...
        computed: {
            list: function() {
                return this.$store.state.transaction.list
            },
            ...
        }
    }
</script>

The result of {{ item.total }} is

26000000

But I want format it to be like this :

26.000.000,00

In jquery or javascript, I can do it

But, How to do it in vue component?

If you can do it in javascript so you can do it in Vue... use computed properties and return the javascript code.

J
Jess

I have created a filter. The filter can be used in any page.

Vue.filter('toCurrency', function (value) {
    if (typeof value !== "number") {
        return value;
    }
    var formatter = new Intl.NumberFormat('en-US', {
        style: 'currency',
        currency: 'USD'
    });
    return formatter.format(value);
});

Then I can use this filter like this:

        <td class="text-right">
            {{ invoice.fees | toCurrency }}
        </td>

I used these related answers to help with the implementation of the filter:

How to format numbers as currency strings

Check whether variable is number or string in JavaScript


My Man! I didn't even know you could do this. Thanks solved my currency problem and cleaned up my mixins since most of them were doing this sort of stuff.
this is the proper answer
How about isNaN(parseFloat(value)) rather than typeof value !== "number"?
i would change the conditional part, because sometimes the database return string, maybe casting the string to number in that conditional would be better, great answer.
It's odd that this answer has specified minimumFractionDigits: 0. I expect most people wanting to format numbers as currencies will, like me, want to have 2 decimal places displayed, e.g. $5.90, rather than $5.9. In that case you can either specify minimumFractionDigits: 2, or indeed just leave that line out altogether since if using style: 'currency' it will default to 2 anyway. Hope this helps someone...
E
Emmathem

UPDATE: I suggest using a solution with filters, provided by @Jess.

I would write a method for that, and then where you need to format price you can just put the method in the template and pass value down

methods: {
    formatPrice(value) {
        let val = (value/1).toFixed(2).replace('.', ',')
        return val.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ".")
    }
}

And then in template:

<template>
    <div>
        <div class="panel-group"v-for="item in list">
            <div class="col-md-8">
                <small>
                   Total: <b>{{ formatPrice(item.total) }}</b>
                </small>
            </div>
        </div>
    </div>
</template>

BTW - I didn't put too much care on replacing and regular expression. It could be improved.enter code here

Vue.filter('tableCurrency', num => { if (!num) { return '0.00'; } const number = (num / 1).toFixed(2).replace(',', '.'); return number.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ','); });


See also developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… for built-in localized currency formatting.
@RoyJ Good catch.I just copied regex from one previous project, basically he could return value from method as he want.
@BelminBedak what do you think of return (value/1).toFixed(2).toLocalString(); ?
Works, but replaces all decimals with commas
Why not use computed instead?
M
Machavity

With vuejs 2, you could use vue2-filters which does have other goodies as well.

npm install vue2-filters


import Vue from 'vue'
import Vue2Filters from 'vue2-filters'

Vue.use(Vue2Filters)

Then use it like so:

{{ amount | currency }} // 12345 => $12,345.00

Ref: https://www.npmjs.com/package/vue2-filters


A
Arkowsky

You can format currency writing your own code but it is just solution for the moment - when your app will grow you can need other currencies.

There is another issue with this:

For EN-us - dolar sign is always before currency - $2.00, For selected PL you return sign after amount like 2,00 zł.

I think the best option is use complex solution for internationalization e.g. library vue-i18n( http://kazupon.github.io/vue-i18n/).

I use this plugin and I don't have to worry about such a things. Please look at documentation - it is really simple:

http://kazupon.github.io/vue-i18n/guide/number.html

so you just use:

<div id="app">
  <p>{{ $n(100, 'currency') }}</p>
</div>

and set EN-us to get $100.00:

<div id="app">
  <p>$100.00</p>
</div>

or set PL to get 100,00 zł:

<div id="app">
  <p>100,00 zł</p>
</div>

This plugin also provide different features like translations and date formatting.


I think this is the best answer.
A
AaronBaker

The comment by @RoyJ has a great suggestion. In the template you can just use built-in localized strings:

<small>
     Total: <b>{{ item.total.toLocaleString() }}</b>
</small>

It's not supported in some of the older browsers, but if you're targeting IE 11 and later, you should be fine.


Simple like this. Confirmed it works. Feel like it should be the selected answer!
A
Andreas Bauer

I used the custom filter solution proposed by @Jess but in my project we are using Vue together with TypeScript. This is how it looks like with TypeScript and class decorators:

import Component from 'vue-class-component';
import { Filter } from 'vue-class-decorator';

@Component
export default class Home extends Vue {

  @Filter('toCurrency')
  private toCurrency(value: number): string {
    if (isNaN(value)) {
        return '';
    }

    var formatter = new Intl.NumberFormat('en-US', {
        style: 'currency',
        currency: 'USD',
        minimumFractionDigits: 0
    });
    return formatter.format(value);
  }
}

In this example the filter can only be used inside the component. I haven't tried to implement it as a global filter, yet.


A
Alexandr Shurigin

You can use this example

formatPrice(value) {
  return value.toString().replace(/(\d)(?=(\d{3})+(?!\d))/g, '$1,');
},

A
Artistan

There is issues with the precision of the accepted answer.

the round(value, decimals) function in this test works. unlike the simple toFixed example.

this is a test of the toFixed vs round method.

http://www.jacklmoore.com/notes/rounding-in-javascript/

Number.prototype.format = function(n) { return this.toFixed(Math.max(0, ~~n)); }; function round(value, decimals) { return Number(Math.round(value+'e'+decimals)+'e-'+decimals); } // can anyone tell me why these are equivalent for 50.005, and 1050.005 through 8150.005 (increments of 50) var round_to = 2; var maxInt = 1500000; var equalRound = '

BEGIN HERE

'; var increment = 50; var round_from = 0.005; var expected = 0.01; var lastWasMatch = true; for( var n = 0; n < maxInt; n=n+increment){ var data = {}; var numberCheck = parseFloat(n + round_from); data.original = numberCheck * 1; data.expected = Number(n + expected) * 1; data.formatIt = Number(numberCheck).format(round_to) * 1; data.roundIt = round(numberCheck, round_to).toFixed(round_to) * 1; data.numberIt = Number(numberCheck).toFixed(round_to) * 1; //console.log(data); if( data.roundIt !== data.formatIt || data.formatIt !== data.numberIt || data.roundIt !== data.numberIt || data.roundIt != data.expected ){ if(lastWasMatch){ equalRound = equalRound + '

Did Not Round UP
' ; document.write('

EXAMPLE: Did Not Round UP: ' + numberCheck + '



'); document.write('expected: '+data.expected + ' :: ' + (typeof data.expected) + '
'); document.write('format: '+data.formatIt + ' :: ' + (typeof data.formatIt) + '
'); document.write('round : '+data.roundIt + ' :: ' + (typeof data.roundIt) + '
'); document.write('number: '+data.numberIt + ' :: ' + (typeof data.numberIt) + '
'); lastWasMatch=false; } equalRound = equalRound + ', ' + numberCheck; } else { if(!lastWasMatch){ equalRound = equalRound + '

All Rounded UP!
' ; } { lastWasMatch=true; } equalRound = equalRound + ', ' + numberCheck; } } document.write('equalRound: '+equalRound + '

');

mixin example

export default { methods: { roundFormat: function (value, decimals) { return Number(Math.round(value+'e'+decimals)+'e-'+decimals).toFixed(decimals); }, currencyFormat: function (value, decimals, symbol='$') { return symbol + this.roundFormat(value,2); } } }


you still could use val.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ".") after that for the . and , changes.
P
Poul Bak

Try this:

methods: {
    formatPrice(value) {
        var formatter = new Intl.NumberFormat('en-US', {
            style: 'currency',
            currency: 'PHP',
            minimumFractionDigits: 2
        });
        return formatter.format(value);
    },
}

Then you can just call this like:

{{ formatPrice(item.total) }}

h
hotcakedev

numeral.js is a JavaScript library for formatting and manipulating numbers.

You can format a currency so easily using it.

For example,

// price = 1200
{numeral(price).format(`$0,0.00`)}

// result $1,200.00

Here's the documentation. http://numeraljs.com/