Faris Dewantoro
Faris Dewantoro

Reputation: 1765

Change format price to rupiah using vue.js

I want to change the format of this price IDR 50,000.00 to be like this IDR 50.000 using JS and Vue.

I got this script from this link but I don't understand how it works. I don't know what is this

replace(/(\d)(?=(\d{3})+(?:\.\d+)?$)/g, "$1,")

so I can't change the format.

Vue.js

<template lang="html">
  <div>
     <input type="text" class="form-control" v-model="displayValue" @blur="isInputActive = false" @focus="isInputActive = true"/>
 </div>
</template>

<script>
export default {
  props: ["value"],
  data: function() {
       return {
           isInputActive: false
       }
   },
   computed: {
       displayValue: {
           get: function() {
               if (this.isInputActive) {
                   // Cursor is inside the input field. unformat display value for user
                   return this.value.toString()
               } else {
                   // User is not modifying now. Format display value for user interface
                   return "IDR " + this.value.toFixed(2).replace(/(\d)(?=(\d{3})+(?:\.\d+)?$)/g, "$1,")
               }
           },
           set: function(modifiedValue) {
               // Recalculate value after ignoring "$" and "," in user input
               let newValue = parseFloat(modifiedValue.replace(/[^\d\.]/g, ""))
               // Ensure that it is not NaN
               if (isNaN(newValue)) {
                   newValue = 0
               }
               // Note: we cannot set this.value as it is a "prop". It needs to be passed to parent component
               // $emit the event so that parent component gets it
               this.$emit('input', newValue)
           }
       }
   }
}
</script>

<style lang="css">
</style>

Upvotes: 2

Views: 6303

Answers (2)

pretzelhammer
pretzelhammer

Reputation: 15115

I changed this line

return "$ " + this.value.toFixed(2).replace(/(\d)(?=(\d{3})+(?:\.\d+)?$)/g, "$1,")

to this

return "IDR " + this.value.toString().replace(/(\d)(?=(\d{3})+(?:\.\d+)?$)/g, "$1\.")

Snippet:

Vue.component('my-currency-input', {
    props: ["value"],
    template: `
        <div>
            <input type="text" v-model="displayValue" @blur="isInputActive = false" @focus="isInputActive = true"/>
        </div>`,
    data: function() {
        return {
            isInputActive: false
        }
    },
    computed: {
        displayValue: {
            get: function() {
                if (this.isInputActive) {
                    // Cursor is inside the input field. unformat display value for user
                    return this.value.toString()
                } else {
                    // User is not modifying now. Format display value for user interface
                    return "IDR " + this.value.toString().replace(/(\d)(?=(\d{3})+(?:\.\d+)?$)/g, "$1\.")
                }
            },
            set: function(modifiedValue) {
                // Recalculate value after ignoring "$" and "," in user input
                let newValue = parseFloat(modifiedValue.replace(/[^\d\.]/g, ""))
                // Ensure that it is not NaN
                if (isNaN(newValue)) {
                    newValue = 0
                }
                // Note: we cannot set this.value as it is a "prop". It needs to be passed to parent component
                // $emit the event so that parent component gets it
                this.$emit('input', newValue)
            }
        }
    }
});

new Vue({
    el: '#app',
    data: function() {
        return {
            price: 50000
        }
    }
});
body {
    margin: 20px;
    font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
}
input {
    border: 1px solid #888;
    font-size: 1.2rem;
    padding: 0.5rem;
}
<script src="https://unpkg.com/[email protected]/dist/vue.js"></script>
<div id="app">
  Price:
  <my-currency-input v-model="price"></my-currency-input>
  <p>
    Price (in parent component): {{price}}
  </p>
</div>

Upvotes: 1

Aslam H
Aslam H

Reputation: 1801

In case you are using jquery I would recommend using the jquery number format. this allow you to automatic formatting of numbers in input elements as you type

Vue.component('idr', {
    template: '<input type="text" class="form-control" v-model="txTotal"/>',
    computed: {
        txTotal: {
            get() {
                return this.value;
            },
            set(val) {
                var rp = val.replace(/[^0-9]/g, '');
                this.$emit('input', rp)
            }
        }
    },
    mounted() {
        $(this.$el).number(true, 0, ',', '.')
    }
})

new Vue({
    el: '#app',
    data: {
        total: '',
    }
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/df-number-format/2.1.6/jquery.number.min.js"></script>

<div id="app">
  <idr @input="total = $event"></idr>
  {{ total }}
</div>

UPDATE WITHOUT JQUERY

Vue.component('idr', {
    template: '<input type="text" v-model="currentValue" @input="handleInput" />',
    props: {
      value: {
        type: [String, Number],
        default: ""
      },
    },
    data: () => ({
      currentValue: ''
    }),
    watch: {
      value: {
        handler(after) {
          this.currentValue = this.format(after)
        },
        immediate: true
      }
    },
    methods: {
      format: value => (value + '').replace(/\D/g, "").replace(/\B(?=(\d{3})+(?!\d))/g, "."),
      
      handleInput() {
        this.currentValue = this.format(this.currentValue)
        this.$emit('input', (this.currentValue + '').replace(/[^0-9]/g, ""))
      }
    }
})

new Vue({
    el: '#app',
    data: {
        total: 5000,
    }
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>

<div id="app">
  <idr v-model="total"></idr>
  {{ total }}
</div>

Upvotes: 1

Related Questions