[vue.js] 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?

This question is related to vue.js vuejs2 vue-component vuex

The answer is


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/

_x000D_
_x000D_
  Number.prototype.format = function(n) {_x000D_
      return this.toFixed(Math.max(0, ~~n));_x000D_
  };_x000D_
  function round(value, decimals) {_x000D_
    return Number(Math.round(value+'e'+decimals)+'e-'+decimals);_x000D_
  }_x000D_
_x000D_
  // can anyone tell me why these are equivalent for  50.005, and 1050.005 through 8150.005 (increments of 50)_x000D_
_x000D_
  var round_to = 2;_x000D_
  var maxInt = 1500000;_x000D_
  var equalRound = '<h1>BEGIN HERE</h1><div class="matches">';_x000D_
  var increment = 50;_x000D_
  var round_from = 0.005;_x000D_
  var expected = 0.01;_x000D_
  var lastWasMatch = true;_x000D_
_x000D_
  for( var n = 0; n < maxInt; n=n+increment){_x000D_
    var data = {};_x000D_
    var numberCheck = parseFloat(n + round_from);_x000D_
    data.original = numberCheck * 1;_x000D_
    data.expected =  Number(n + expected) * 1;_x000D_
    data.formatIt = Number(numberCheck).format(round_to) * 1;_x000D_
    data.roundIt = round(numberCheck, round_to).toFixed(round_to) * 1;_x000D_
    data.numberIt = Number(numberCheck).toFixed(round_to) * 1;_x000D_
    //console.log(data);_x000D_
_x000D_
    if( data.roundIt !== data.formatIt || data.formatIt !== data.numberIt ||_x000D_
       data.roundIt !== data.numberIt || data.roundIt != data.expected_x000D_
      ){_x000D_
        if(lastWasMatch){_x000D_
          equalRound = equalRound + '</div><div class="errors"> <hr/> Did Not Round UP <hr/>' ;_x000D_
            document.write(' <h3>EXAMPLE: Did Not Round UP: ' + numberCheck + '</h3><br /><hr/> ');_x000D_
            document.write('expected: '+data.expected + ' :: ' + (typeof data.expected)  + '<br />');_x000D_
            document.write('format: '+data.formatIt + ' :: ' + (typeof data.formatIt)  + '<br />');_x000D_
            document.write('round : '+data.roundIt + ' :: ' + (typeof data.roundIt)  + '<br />');_x000D_
            document.write('number: '+data.numberIt + ' :: ' + (typeof data.numberIt)  + '<br />');_x000D_
            lastWasMatch=false;_x000D_
        }_x000D_
        equalRound = equalRound + ', ' + numberCheck;_x000D_
    } else {_x000D_
        if(!lastWasMatch){_x000D_
          equalRound = equalRound + '</div><div class="matches"> <hr/> All Rounded UP! <hr/>' ;_x000D_
        } {_x000D_
            lastWasMatch=true;_x000D_
        }_x000D_
        equalRound = equalRound + ', ' + numberCheck;_x000D_
    }_x000D_
  }_x000D_
  document.write('equalRound: '+equalRound + '</div><br />');
_x000D_
_x000D_
_x000D_

mixin example

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


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

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


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.


You can use this example

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

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.


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',
        minimumFractionDigits: 0
    });
    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:


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:

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

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 zl:

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

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


Examples related to vue.js

How to fix 'Unchecked runtime.lastError: The message port closed before a response was received' chrome issue? Center content vertically on Vuetify Vue.js get selected option on @change Using Environment Variables with Vue.js did you register the component correctly? For recursive components, make sure to provide the "name" option Vue 'export default' vs 'new Vue' How can I go back/route-back on vue-router? Change the default base url for axios How to reference static assets within vue javascript How to change port number in vue-cli project

Examples related to vuejs2

How can I go back/route-back on vue-router? Change the default base url for axios How to change port number in vue-cli project How to solve 'Redirect has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header'? vuetify center items into v-flex Vuejs: Event on route change Vuex - Computed property "name" was assigned to but it has no setter Vuex - passing multiple parameters to mutation How to listen to the window scroll event in a VueJS component? How to acces external json file objects in vue.js app

Examples related to vue-component

Vue 'export default' vs 'new Vue' Vuex - Computed property "name" was assigned to but it has no setter How to add external JS scripts to VueJS Components How to listen for 'props' changes How can I set selected option selected in vue.js 2? How do I format currencies in a Vue component? [Vue warn]: Property or method is not defined on the instance but referenced during render VueJs get url query Vue.js - How to properly watch for nested data Vue template or render function not defined yet I am using neither?

Examples related to vuex

Vuex - Computed property "name" was assigned to but it has no setter Vuex - passing multiple parameters to mutation vue.js 2 how to watch store values from vuex How do I format currencies in a Vue component? Returning Promises from Vuex actions