9

Only allow users to key in value like currency in a text box by using Vue.js

Saviah Kao
  • 320
  • 1
  • 5
  • 13
  • Imho, there ought exist a predefined way of doing it or at least have a regex/pattern way of doing it... Someone let me/us know if or when it is there... – Dirk Schumacher Nov 18 '20 at 12:22

3 Answers3

16

Working example: https://jsfiddle.net/0s14cbqx/

In template:

<input placeholder="Name a price" v-model="price" @keypress="onlyForCurrency">

In js:

data(){
   return{
     price:null
   }
},
methods: {
   onlyForCurrency ($event) {
     // console.log($event.keyCode); //keyCodes value
     let keyCode = ($event.keyCode ? $event.keyCode : $event.which);

     // only allow number and one dot
     if ((keyCode < 48 || keyCode > 57) && (keyCode !== 46 || this.price.indexOf('.') != -1)) { // 46 is dot
      $event.preventDefault();
     }

     // restrict to 2 decimal places
     if(this.price!=null && this.price.indexOf(".")>-1 && (this.price.split('.')[1].length > 1)){
     $event.preventDefault();
     }
   }
}

In this way, users only can key in numbers and one dot and can't key in anything after 2 decimal places.

Saviah Kao
  • 320
  • 1
  • 5
  • 13
  • Works great, but word of warning as I was stuck replicating this for ages!! Setting the input to `type="number"` causes problems! As explained here I discovered - https://stackoverflow.com/questions/46650472/how-can-i-disable-all-dot-on-input-type-number-vue-js-2 – Jquestions Feb 06 '19 at 17:36
  • 3
    Also - there is an issue editing the number once it's typed. Cannot go back and edit. I'm not sure how to change to make work.... any ideas? It's the 2nd if statement. – Jquestions Feb 07 '19 at 17:20
  • 2
    @Jquestions if the input is type="text" you can add: `$event.target.selectionStart > this.price.indexOf(".")` to the last if statement to only prevent typing numbers if you are after the dot. – Crompy Oct 17 '19 at 00:58
  • Please be aware that keypress event is deprecated https://developer.mozilla.org/en-US/docs/Web/API/Document/keypress_event – Piotr Żak Oct 16 '20 at 11:52
8

For input with type number, this is what we settled with:

<input type="number" v-model.number="price" @input="handleInput">
  data () {
    return {
      price: null,
      previousPrice: null
    }
  },

  methods: {
    handleInput (e) {
      let stringValue = e.target.value.toString()
      let regex = /^\d*(\.\d{1,2})?$/
      if(!stringValue.match(regex) && this.price!== '') {
        this.price = this.previousPrice
      }
      this.previousPrice = this.price
    }
  }

The idea is to check the user's input result. If it doesn't match the required regex pattern, then we reset the data back to its previous state using previousPrice. Demo: https://jsfiddle.net/edwardcahyadi/qj9mw5gk/2/

Edward Cahyadi
  • 450
  • 5
  • 9
4

Using the autoNumeric Javascript library works very well.

There is a Vue.js component that wraps it: vue-autoNumeric.

Also, it works well with Vuetify's v-text-field, see https://codesandbox.io/s/yw07v978mj.

Renaud Tarnec
  • 79,263
  • 10
  • 95
  • 121
  • 2
    Regarding the code sandbox you provided - you should also detach the element in `beforeDestroy` to avoid memory leak. – Yihao Gao Oct 03 '21 at 10:54