Input with type="number" that allows only numbers to be typed
Asked Answered
L

4

8

I want to make an Input-Field in which you can only write natural numbers. (Yes, I know this can be a bad practice, as the user doesn't get any feedback). If you type anything else than a digit, it should not appear in the input. I want to use plain JavaScript (no JQuery).

This is how I'd do it normally:

<input oninput="this.value = this.value.replace(/\D+/g, '')">

But I found out, that <input type="number"> is much preferred for mobile devices, as it doesn't show the whole keyboard, but just digits.

So my question is, how can I combine type="number" with the filtering (and make it compatible with Cut/Copy/Paste)?

The value of the <input type="number">-element is always an empty String if any non-number-character is entered. So my filtering method from above doesn't work. Is there any workaround?

If not, I'd have to listen for keydown, paste, cut, and possibly many more events. Which events would I have to consider, how would I implement it, and is there any easier way I have overlooked?

Laudian answered 15/7, 2021 at 13:11 Comment(5)
What is missing from <input type="number" /> ??? It is not clear what you cannot do with type="number" - a user cannot type anything other than numbers in thatNonexistence
@Nonexistence I suppose it doesn't get in the way of the users enough.Matrimony
@Nonexistence You CAN type any character in an input with type="number". It's just not valid. But I want to completely stop a user from typing other characters in the input box.Laudian
@Laudian https://mcmap.net/q/1254031/-input-with-type-quot-number-quot-that-allows-only-numbers-to-be-typedNonexistence
What browser are you using, input type number does not allow me to type anything I want.Deplane
A
14

Try using inputmode attribute

https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/inputmode

<input inputmode="numeric" oninput="this.value = this.value.replace(/\D+/g, '')"  />

References

https://css-tricks.com/finger-friendly-numerical-inputs-with-inputmode

Asarum answered 15/7, 2021 at 13:30 Comment(0)
O
3

Here is a solution using HTML and vanilla JS:

function setInputFilter(textbox, inputFilter) {
  ["input", "keydown", "keyup", "mousedown", "mouseup", "select", "contextmenu", "drop"].forEach(function(event) {
    textbox.addEventListener(event, function() {
      if (inputFilter(this.value)) {
        this.oldValue = this.value;
        this.oldSelectionStart = this.selectionStart;
        this.oldSelectionEnd = this.selectionEnd;
      } else if (this.hasOwnProperty("oldValue")) {
        this.value = this.oldValue;
        this.setSelectionRange(this.oldSelectionStart, this.oldSelectionEnd);
      } else {
        this.value = "";
      }
    });
  });
}

setInputFilter(document.getElementById("numTxtBox"), function(value) {
  return /^-?\d*$/.test(value); });
  <tr><td>Number Only </td><td><input id="numTxtBox"></td></tr>

UPDATE:

The above code does malfunction in Firefox and Chrome.

Here is an alternate solution that works across all browsers!

function validate(num) {
  var theEvent = num || window.event;

  // Handle paste
  if (theEvent.type === 'paste') {
      var key = event.clipboardData.getData('text/plain');
  } else {
  // Handle key press
      var key = theEvent.keyCode || theEvent.which;
      key = String.fromCharCode(key);
  }
  var regex = /[0-9]|\./;
  if( !regex.test(key) ) {
    theEvent.returnValue = false;
    if(theEvent.preventDefault) theEvent.preventDefault();
  }
}
<input type='number' onkeypress='validate(event)' onpaste='validate(event)' />
Ordonez answered 15/7, 2021 at 13:14 Comment(8)
This does not work. Change <input id="numTxtBox"> to <input id="numTxtBox" type="number"> (as required by the question) and it will break.Laudian
@Laudian What do you mean? In this example right here it only allows integer numbers to be inserted, as well as copied/pasted/Ctrl+A? You should not need input type="number" as this is a workaround. It is redundant to set the typeOrdonez
input type="number" is required for mobile devices to suggest users a digit-keyboard, instead of the usual letter-keyboard. This is the whole point of the question. Please fully read the question.Laudian
What do you mean by it breaks? This fiddle says otherwise setting the type="number" jsfiddle.net/BeerusDev/18Ls7bdpOrdonez
With "it breaks" i mean, that the JS Code doesn't work anymore. You can type non-number-characters in the input, after adding type="number" to it. Try it with Firefox. (Chrome and Edge block you from entering non-number characters in a type="number" input by standard. Firefox doesn't.)Laudian
@Laudian added an update that works across all browsers!Ordonez
onkeypress doesn't fire when you paste something. So it doesn't handle paste. But the fix is rather simple: (added "onpaste=..."). <input type='number' onkeypress='validate(event)' onpaste='validate(event)'/> Plus, the Var (for the key) is at the wrong position. I'd put it infront of the if: var key; if (theEvent.type ...) { key = ...; } else { key = ...; key = ...; }Laudian
Didn't even notice that, thank you for pointing it out! If my answer helped you please don't forget to mark it as accepted! Have a great dayOrdonez
N
3

Tested in Chrome (cannot enter anything else than numbers, - and e

In Firefox you can type but not submit

Try typing anything and then hit enter
<form>
<input type="number" required />
</form>

Let's try this then - if it is ok to clear the field when typing a char, we do not need keyUp or such

Firefox will return empty string if you type a char anywhere, Chrome will not allow the char

document.querySelector("form").addEventListener("input",function(e) {
  const tgt = e.target;
  if (tgt.type && tgt.type==="number") { 
    const val = tgt.value;
    const nums = val.replace(/[^\d.-]/g, '');
    if (!/\d+/.test(val)) tgt.value="";
  }  
})
Try typing anything and then hit enter
<form>
<input type="number" required />
</form>
Nonexistence answered 15/7, 2021 at 13:17 Comment(6)
I'm on a desktop computer (windows) using a Firefox browser (newest version). Here you can. I can test other browsers If you want, but I strongly assume it will give the same result.Laudian
Ah, I only use Chrome(ium)Nonexistence
@Laudian you can write them but they aren't valid. The form cannot be submitted if you have 1a2.Matrimony
Yes, I know It will not be valid. But I want to stop the user from typing non-digits characters in the input box in the first place.Laudian
@Laudian But I want to stop the user, that's usually not a good way to treat a user, for example I might want to use Firefox as it allows me to paste the value amount=£12.00, and then delete the parts I don't want. If I don't like this feature of Firefox, I would instead use Chrome. In both browsers when submitted with invalid values it errors, and from a users POV surely this is the part that matters. Of course your the developer, and if this is important then totally understandable, but as a web developer it's very easy to be controlling, when in fact it ends up been a negative.Deplane
@Laudian As a final note!!, pretty much every website I've used were the developer has tried to be clever with it's inputs, even when using tried and tested UI kits, like JQueryUI etc, they usually end up been the most awkward websites to use, especially when on mobile. In your case there may be a very good reason, but it's just something to be aware off.Deplane
W
1
<input onkeydown=this.isNumberInputOnly />

and the function

function isNumberOnlyInput(event) {
    if (!parseInt(event.key) && event.key != 'Backspace') {
        event.preventDefault();
    }
}

can roughly do the trick

Wirer answered 8/2 at 10:40 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.