Creating an HTML5 Integer Input

When the HTML5 Number Input Is Not Enough

By Michael Chang

December 2nd, 2020

image

My Journey

More often than not when dealing with numerical inputs, I need an integer input. For example, you can only add an integer quantity of items to a shopping cart. Imagine trying to buy a fraction of an iPhone! Unfortunately, the input number type doesn’t support this out of the box — but it can. Let’s dive into how.

Integer Input

The input number type takes us mostly there but unfortunately it supports decimals (e.g. 1.234) and scientific notation (e.g. 1e10) as well. Fortunately there’s an incredibly simple way to ignore these undesirable characters using onKeyPress. This event handler is triggered before the onChange function. This means that you can use onKeyPress to check what is key pressed and ignore the input if it is an unwanted character.

<input
  onChange={e => onChange(e.target.value)}
  onKeyPress={e => {
    if (!/[-\d]/.test(e.key)) {
      e.preventDefault();
    }
  }}
  type="number"
  value={value}
/>

If the key pressed (checked via e.key) is not a number or a dash (to support negative integers), the default behavior will be prevented and the onChange function will not be triggered. Effectively, this will prevent the character from being entered into the input. That’s pretty much it!

Alternatives

onKeyPress method isn’t the only way to create an integer input.

Pattern allows you to specify a regex string that will be matched with the input when the form is submitted. If the input does not match the regex, the form will not be submitted. For an integer input, this should be set to [-\d] just like the onKeyPress method to only allow dashes and numbers.

<input
  onChange={e => onChange(e.target.value)}
  pattern="[-\d]"
  type="number"
  value={value}
/>

Step allows you to specify the interval between valid numbers. If the input is not divisible by the specified step, the form will not be submitted. For an integer input, this should be set to 1.

<input
  onChange={e => onChange(e.target.value)}
  step="1"
  type="number"
  value={value}
/>

Both of these methods, while valid, requires the user to submit the form first. Only then, will the user be informed of the error. I personally don’t like these methods since I prefer providing user immediate feedback — either not allowing the user to enter an invalid value in the first place or showing an error immediately. Doing so later during submission will confuse the user.

Final Thoughts

I really wish there was a native HTML5 for integer given how many common use-cases there are. But even without a native implementation, it’s pretty easy to implement on your own.

Resources



Continue Learning