Filter input text only accept number and dot vue.js

vue.js

vue.js Problem Overview


I have a text box and only want to accept numbers and a period "." when using VueJS. Can anyone help with code? I'm new to Vue.

vue.js Solutions


Solution 1 - vue.js

You can write a Vue method and that method can be called on the keypress event. Check out this fiddle.

Update:

adding source code:

###HTML

<div id="demo">
  <input v-model="message" @keypress="isNumber($event)">
</div>

###Vue.js

var data = {
  message: 1234.34
}

var demo = new Vue({
  el: '#demo',
  data: data,
  methods: {
    isNumber: function(evt) {
      evt = (evt) ? evt : window.event;
      var charCode = (evt.which) ? evt.which : evt.keyCode;
      if ((charCode > 31 && (charCode < 48 || charCode > 57)) && charCode !== 46) {
        evt.preventDefault();;
      } else {
        return true;
      }
    }
  }
});

Solution 2 - vue.js

You should change your input to type="number" to more accurately reflect your behaviour. You can then use the built-in Vue.js directive v-model.number.

Usage:

<input type="number" v-model.number="data.myNumberData"/>

Solution 3 - vue.js

This was my solution. Most of the answers here have been deprecated. Additionally, input values always return a string, even if you key a number. So because of that, some of the solutions here did not work for me.

In my case I didn't want a decimal point, but I added that into the array for the purpose of this thread.

<b-form-input v-model.number="quantity" @keypress="isNumber($event)" type="number"></b-form-input>
isNumber (evt: KeyboardEvent): void {
    const keysAllowed: string[] = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '.'];
    const keyPressed: string = evt.key;
    
    if (!keysAllowed.includes(keyPressed)) {
           evt.preventDefault()
    }
}

Solution 4 - vue.js

Short and easy understand.

HTML

 <input @keypress="onlyNumber" type="text">

VUE JS

onlyNumber ($event) {
   //console.log($event.keyCode); //keyCodes value
   let keyCode = ($event.keyCode ? $event.keyCode : $event.which);
   if ((keyCode < 48 || keyCode > 57) && keyCode !== 46) { // 46 is dot
      $event.preventDefault();
   }
}

Solution 5 - vue.js

A simple way to do this in one line:

IsNumber(event) {
  if (!/\d/.test(event.key) && event.key !== '.') return event.preventDefault();
}

Solution 6 - vue.js

Here is a better way to handle the specific question asked (numbers and "dots" only) by setting v-restrict.number.decimal using the following directive. It also had some bonus code to support alpha only or alphanumeric. You could also only allow "dots" although I do not know why you would. It will not allow extra characters to "sneak through" if typing fast. It also supports copy/paste, delete, and some other keys users would expect to still work from an input:

Vue.directive('restrict', {
  bind (el, binding) {
    el.addEventListener('keydown', (e) => {
      // delete, backpsace, tab, escape, enter,
      let special = [46, 8, 9, 27, 13]
      if (binding.modifiers['decimal']) {
        // decimal(numpad), period
        special.push(110, 190)
      }
      // special from above
      if (special.indexOf(e.keyCode) !== -1 ||
        // Ctrl+A
        (e.keyCode === 65 && e.ctrlKey === true) ||
        // Ctrl+C
        (e.keyCode === 67 && e.ctrlKey === true) ||
        // Ctrl+X
        (e.keyCode === 88 && e.ctrlKey === true) ||
        // home, end, left, right
        (e.keyCode >= 35 && e.keyCode <= 39)) {
        return // allow
      }
      if ((binding.modifiers['alpha']) &&
        // a-z/A-Z
        (e.keyCode >= 65 && e.keyCode <= 90)) {
        return // allow
      }
      if ((binding.modifiers['number']) &&
        // number keys without shift
        ((!e.shiftKey && (e.keyCode >= 48 && e.keyCode <= 57)) ||
        // numpad number keys
        (e.keyCode >= 96 && e.keyCode <= 105))) {
        return // allow
      }
      // otherwise stop the keystroke
      e.preventDefault() // prevent
    }) // end addEventListener
  } // end bind
}) // end directive

To use:

<!-- number and decimal -->
<input
  v-model="test"
  v-ep-restrict.number.decimal
  ...
/>

<!-- alphanumeric (no decimal) -->
<input
  v-model="test2"
  v-ep-restrict.alpha.number
  ...
/>

<!-- alpha only -->
<input
  v-model="test3"
  v-ep-restrict.alpha
  ...
/>

This can be modified to serve as a base for just about any scenario and a good list of key codes is here

Solution 7 - vue.js

I solved issue like yours via vue.js filters. First i created filter - let's say in filters.js file

export const JustDigits = () => {
  Vue.directive('digitsonly', (el, binding) => {
    if (/[\d\.]+/i.test(el.value)) {
      console.log('ok');
    } else {
      let newValue = el.value.replace(/[a-zA-Z]+/ig, '');
      el.value = newValue;
      console.log('should fix', newValue);
      binding.value = el.value;
    }
  });
};

Then in the component where this functionality is required i did:

import {
  JustDigits
} from './filters';

JustDigits();

And then you are able to use this directive in template:

 <input  v-model="myModel"
         v-digitsonly
         type="text"  
         maxlength="4"  class="form-control" id="myModel" name="my_model" />

Please note, that my regex may differ from what you need, feel free to modify it as well as this code line let newValue = el.value.replace(/[a-zA-Z]+/ig, ''); that removes characters from the string. I posted it just to show you one of the possible solutions vue.js provides to solve task like this.

Solution 8 - vue.js

Building on previous solutions, to prevent multiple decimal positions, also pass the v-model to the function:

<input v-model="message" v-on:keypress="isNumber($event, message)">

and modify the isNumber method as follows:

isNumber(event, message) {
  if (!/\d/.test(event.key) &&  
    (event.key !== "." || /\./.test(message))  
  )  
    return event.preventDefault();  
}

To limit the number of digits after the decimal add the following line into the isNumber method:

 if (/\.\d{2}/.test(message)) return event.preventDefault();

The \d{2} limits the entry of two digits. Change this to \d{1} to limit to one.

As stated in other answers, this does not prevent the pasting of non-numeric data.

Solution 9 - vue.js

I needed my input to allow only digits, so no e symbol, plus, minus nor .. Vue seems funky and doesn't re-trigger @onkeypress for symbols like dot.

Here is my solution to this problem:

<input
  onkeypress="return event.key === 'Enter'
    || (Number(event.key) >= 0
    && Number(event.key) <= 9"
  type="number"
>

I am taking digits only, limiting from 0 to 9, but also I do want enable form submit on Enter, which would be excluded with the above approach - thus the enter.

Solution 10 - vue.js

You can handle this via simple html

<input type="number">

and in your app.css

/* Chrome, Safari, Edge, Opera */
input::-webkit-outer-spin-button,
input::-webkit-inner-spin-button {
  -webkit-appearance: none;
  margin: 0;
}

/* this is for Firefox */
input[type=number] {
  -moz-appearance: textfield;
}

Style code will remove ugly arrows from your number input field and yes it accepts dots

Solution 11 - vue.js

<v-text-field class='reqField' label="NUMBER" @keypress="isNumber($event)"></v-text-field>
methods: {
	isNumber: function(evt) {
		evt = (evt) ? evt : window.event;
		var charCode = (evt.which) ? evt.which : evt.keyCode;
		if (charCode > 31 && (charCode < 48 || charCode > 57) && (charCode != 9)) {
			evt.preventDefault();
		} else {
			return true;
		}
		`enter code here`
	},
}

Solution 12 - vue.js

Why not using an external mask lib like vue-the-mask or cleave.js?

For example, with vue-the-mask you can easily use theirs directive like this:

<input type="text" name="some-name" id="some-id" v-model="some.value" v-mask="'##.##.##.##.###'">

Solution 13 - vue.js

You can use this library https://www.npmjs.com/package/vue-input-only-number

import onlyInt, { onlyFloat } from 'vue-input-only-number';

Vue.use(onlyInt);
Vue.use(onlyFloat);

<input type="text" v-int>
<input type="text" v-float>

Solution 14 - vue.js

Just evaluate if is nan and now you can prevent default

<input @keypress="isNumber">

isNumber (val) {
  if (isNaN(Number(val.key))) {
    return val.preventDefault();
  }
}

Solution 15 - vue.js

I cannot the perfect solution as some work for input but not for copy&paste, some are the other way around. This solution works for me. It prevents negative numbers, typing "e", copy&paste "e" text.

I use mixin so I can be reused anywhere.

const numberOnlyMixin = {
    directives: {
    numericOnly: {
        bind(el, binding, vnode) {

        // console.log(el, binding);

        // this two prevent from copy&paste non-number text, including "e".
        // need to have both together to take effect.
        el.type = 'number';
        el.addEventListener('input', (e) => {
            // console.log('input', e);
            // console.log(el.validity);
            return el.validity.valid || (el.value = '');
        });

        // this prevents from typing non-number text, including "e".
        el.addEventListener('keypress', (e) => {
            let charCode = (e.which) ? e.which : e.keyCode;
            if ((charCode > 31 && (charCode < 48 || charCode > 57)) && charCode !== 46) {
            e.preventDefault();
            } else {
            return true;
            }
        });
        }
    }
    },
};

export {numberOnlyMixin}

In your component, add to your input.

<input v-model="myData" v-numericOnly />

Solution 16 - vue.js

There is input event that reacts on any type of change(program or user type) which is more powerful than keypress or keydown.

<input @input="preventInvalidInput">
preventInvalidInput(event) {
  let value = event.target.value;
  // Check if value is number
  let isValid = +value == +value;
	
  if (!isValid) {
	// input event is not cancellable by preventDefault() 
    // so we have to use the below approach to reset the current value to previous one
	var resetEvent = document.createEvent('Event');
	resetEvent.initEvent('input', true, true);
	event.target.value = event.target._value;
	event.target.dispatchEvent(resetEvent);
  }
}

Solution 17 - vue.js

You can use the number type in it:

<input type="number" class="yourCssClass" placeholder="someText" id="someId" />

and then, add the CSS required to remove the up/down spinners:

/* Chrome, Safari, Edge, Opera */
  input::-webkit-outer-spin-button,
  input::-webkit-inner-spin-button {
    -webkit-appearance: none;
    margin: 0;
  }

  /* Firefox */
  input[type=number] {
    -moz-appearance: textfield;
  }

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionMuh Ghazali AkbarView Question on Stackoverflow
Solution 1 - vue.jsDeendayal GargView Answer on Stackoverflow
Solution 2 - vue.jsJBeagleView Answer on Stackoverflow
Solution 3 - vue.jsBrian KoppView Answer on Stackoverflow
Solution 4 - vue.jsMengseng OengView Answer on Stackoverflow
Solution 5 - vue.jsVinicius GaglianoView Answer on Stackoverflow
Solution 6 - vue.jsD DurhamView Answer on Stackoverflow
Solution 7 - vue.jsflamedmgView Answer on Stackoverflow
Solution 8 - vue.jsSteveCView Answer on Stackoverflow
Solution 9 - vue.jsAdamView Answer on Stackoverflow
Solution 10 - vue.jselvonkhView Answer on Stackoverflow
Solution 11 - vue.jsRajendra RajputView Answer on Stackoverflow
Solution 12 - vue.jsPablo SouzaView Answer on Stackoverflow
Solution 13 - vue.jstrueborodaView Answer on Stackoverflow
Solution 14 - vue.jsAndres FelipeView Answer on Stackoverflow
Solution 15 - vue.jsArstView Answer on Stackoverflow
Solution 16 - vue.jsMaksim ShamihulauView Answer on Stackoverflow
Solution 17 - vue.jsundertugaView Answer on Stackoverflow