Search code examples
javascriptvue.jslocalization

How make VueJS understand localized numbers?


Let's figure a simple sum app. two inputs, a and b and a c result.

we have this markup

<div id="app">
<input v-model.number="v1">
<input v-model.number="v2">
{{v3}}
</div>

and this Vue script

var vm = new Vue ({
    el: "#app",
       data: {
        a:0,
        b:0,
    },        
    computed: {
     c:function(){
            return this.a + this.b; 
        }
    }
})

this works great except that I'm working with localized numbers. that means. using comma "," instead of dot "." and dot instead of comma .

entering number with decimal places confuses vue, and it are not able to make a correct sum.

What can I do in order to make VueJS understand localized number input and them make the correct sum?

for instance in pt-BR locale: 1.000,30 + 100,30 = 1.100,60


Solution

  • Well, first of all, a number is just a number. Internally, the . will always be the decimal separator.

    So a number like 1.100,60 is the number 1100.60 just printed in a different locale.

    To print it, just use JavaScript's Number#toStringLocale():

    var vm = new Vue({
      el: "#app",
      data: {
        a: 1110.12,
        b: 10000.11,
      },
      computed: {
        c: function() {
          return this.a + this.b;
        }
      }
    })
    <script src="https://unpkg.com/vue@2"></script>
    
    <div id="app">
      <input v-model.number="a">
      <input v-model.number="b">
      <hr>
      Browser's locale: {{c.toLocaleString()}}<br>
      en-US locale: {{c.toLocaleString('en-US')}}<br>
      pt-BR locale: {{c.toLocaleString('pt-BR')}}<br>
    </div>

    Using a formatted <input>

    Now, if you want the <input> to take localized numbers, that is not a problem specific to Vue, but to JavaScript and the browser in general. This means that you'll have to find a custom component that implements the behavior you want (formatting in the <input>).

    Luckily, a quick search brings one that seems to to the job:

    Vue.use(VueNumeric.default)
    var vm = new Vue({
      el: "#app",
      data: {
        a: 1110.12,
        b: 10000.11,
      },
      computed: {
        c: function() {
          return this.a + this.b;
        }
      }
    })
    <script src="https://unpkg.com/accounting-js"></script>
    <script src="https://unpkg.com/vue@2"></script>
    <script src="https://unpkg.com/vue-numeric"></script>
    
    <div id="app">
      Formatted inputs:
      <vue-numeric currency="R$" separator="," precision="2" v-model="a"></vue-numeric>
      <vue-numeric currency="$" separator="." precision="2" v-model="b"></vue-numeric>
      <hr>
      Browser's locale: {{c.toLocaleString()}}<br>
      en-US locale: {{c.toLocaleString('en-US')}}<br>
      pt-BR locale: {{c.toLocaleString('pt-BR')}}<br>
    </div>

    Again, the component just changes the input field. The number will still be just a number and the "printing" will still have to be done using .toLocaleString().