How to allow only digits to be entered into an input[type="number"] field?

HTML 4 has an event called onkeypress. With that attribute we can do this without using additional JS:

<input type="number" onkeypress="return (event.charCode == 8 || event.charCode == 0 || event.charCode == 13) ? null : event.charCode >= 48 && event.charCode <= 57">

Here digits from 0 to 9 are allowed using the event.charCode from 48 to 57.


I think the reason that the browser clean the input value it is because a string with two dots it is not a number.

Some corrections about your code:

You need to change your expression regular if you want to accept number with decimal part. Now, you are only express that you want to accept digits [0-9] and no more chars.

To accomplish want you want, you need to change /[^\d]/g to /[^\d.]/g.

document.getElementById("integer").addEventListener('input', restrictToInteger);

function restrictToInteger()
{
  this.value = this.value.replace(/[^\d.]/g, '');
}
<input type="number" id="integer" />

HOWEVER: If you define your input as number type, the regular expression is not needed. So, you just need to define the input like this and should your to your case:

<input type="number" id="integer" />

[THE SOLUTION]

To fully meet your needs, I came with a solution that catch the keydown event of the input and check if there is any '.' on the input. If yes, I prevent the char to go to the input.

document.getElementById("integer").addEventListener('keydown', restrictToInteger);
var lastCodeWasDot = false;
function restrictToInteger(e)
{
   var inputValue = document.getElementById("integer").value;
   var isDot = false;
   var isDot = (e.keyCode && e.keyCode == 110) || (e.charCode && e.charCode == 190);
   console.log(e.keyCode);
   if(isDot && (inputValue.indexOf(".") > -1 || inputValue == "" || lastCodeWasDot)) {
       e.preventDefault();
   }
   lastCodeWasDot = isDot;
   
}
<input type="number" id="integer" />

Explaning the solution:

The line of code var isDot = (e.keyCode && e.keyCode == 110) || (e.charCode && e.keyCode == 190) || false; is needed because cross browser compatibility.

I don't now why but if you try to get the value from an input number type in the firefox, and if the value finishes with a dot, the value that you will get will be without the last dot of the input. To fix that, I needed to add the variable lastCodeWasDot to fix this issue.

NOTE: The number input can accept floating point numbers, including negative symbols and the e or E character (check out this post)


Based on the answers of Alexandru-Ionut Mihai and natchiketa I created the following solution:

document.getElementById("integer").addEventListener("input", allowOnlyDigits);

function allowOnlyDigits() {  
  if (this.validity.valid) {
    this.setAttribute('current-value', this.value.replace(/[^\d]/g, ""));
  }
  this.value = this.getAttribute('current-value');
}
<input type="number" id="integer" />

On input the value is checked for validity. If it is valid, all non-digits are removed and the value is stored in a custom attribute of the element. If the value is not valid, the previous value is restored.

Notes:

  • The RegEx-replace is required only for Internet Explorer as it allows you to enter , or . at the end of a number.
  • Tested in IE, Edge, Chrome and Firefox
  • Chrome still allows you to enter a + before and one , after the number.
  • I found one issue: If you initialize the field with a value, the value is lost when you first hit an invalid char on the keyboard.
  • Another issue: You can't enter a negative number.