0

I am trying to build an only numeric field with VueJS. It kind of works but something is wrong:

  1. PASS: Enter 12 in the text field, the value in VueJS is 12, the visual is 12.
  2. FAILS: Enter 12a in the text field, the value in VueJS is 12, the visual is 12a. (expected behaviour is 12 in the text field)
  3. PASS: Enter 12a4 in the text field, the value in VueJS is 12a4, the visual is 124

You can try with this JSFiddle I made: https://jsfiddle.net/El_Matella/rr2qex8k/

Here is my text field component:

const TextField = {
    template: '<div><input type="text" v-model="copy"></div>',
        props: ['value'],
        data () {
        return {
            copy: null
        }
    },
    created () {
        this.copy = this.value.toString()
    },
    watch: {
        value () {
            this.copy = this.value.toString()
        },
        copy () {
            this.$emit('input', this.copy)
        }
    }
}

Here is the code that should allow me to use that text field component as an only numeric text:

new Vue({
    el: '#app',
    data: {
        number: 1
    },
    methods: {
        update (value) {
            this.number = parseInt(value.replace(/\D/g, ''))
        }
    },
    components: {
        TextField
    }
})

The problem is that the input field does not update when the last entered char is a non numeric value. You have to enter an other numeric value in order to update the input and remove the non numeric chars.

Hammerbot
  • 15,696
  • 9
  • 61
  • 103
  • Hi, maybe using `type="number"` and removing the string transformations `this.copy = this.value.toString()` in created and watch will help? – Nora Mar 06 '18 at 14:43
  • It does indeed, however I would have prefer not to have the little arrows at the end of the input: https://jsfiddle.net/El_Matella/rr2qex8k/7/ – Hammerbot Mar 06 '18 at 14:46
  • See https://stackoverflow.com/questions/39782176/filter-input-text-only-accept-number-and-dot-vue-js/64974337#64974337 – Maksim Shamihulau Nov 24 '20 at 12:11

2 Answers2

4

try this on your input tag

<input type="text" onkeypress='return event.charCode >= 48 && event.charCode <= 57'/>

or

<input type="number" />

you can check for compatibility here:

https://caniuse.com/#search=type%3D%22number%22

LPZadkiel
  • 561
  • 1
  • 3
  • 16
  • This does work indeed: https://jsfiddle.net/El_Matella/rr2qex8k/15/ are the `charCode` the same on each browsers? – Hammerbot Mar 06 '18 at 14:52
  • yes, that is ASCII related, from 48 to 57 are the codes for 0 to 9 characters, consider that with this you can't insert negative chart "-" – LPZadkiel Mar 06 '18 at 14:55
0

You can use a getter and setter on a computed value to cleanse your input value on the way in:

const TextField = {
    template: '<div><input type="text" v-model="inputValue"></div>',
    props: ['value'],
    data(){
        return {
            number: 0
        }
    },
    computed: {
        inputValue: {
            get: function(){
                return this.number;
            },
            set: function(value){
                this.number = parseInt(value.replace(/\D/g, ''))
            }
        }
    }
}
Jeff
  • 24,623
  • 4
  • 69
  • 78