Allow MaxLength and only numeric characters in <input> tag with number attribute

The right way to input whole numbers in web applications.

Nikhil Malhotra
3 min readJul 7, 2020

The <input> tag offers type attribute with value number which is a new type from the HTML5 specification. We often use this type whenever there is a need for numbers only input. But it also causes problems whenever we need to add limits or accept only whole numbers as it also accepts “+”, “-”, “.” and “e”.

Note : The code has been written in React.js. For vanilla JavaScript just use attributes in lower case and pass “event” in function for e.g. onkeydown="checkLength(event)"

maxLength attribute is not recognised when type="number" is used.

This will create problems while specifying limits if we need input as numbers only. To resolve this we can use onKeyDown and maxLength in the following way:

<input id="inputText" 
type="number"
maxLength="10"
onKeyDown={e=>this.checkLength(e)}
/>
checkLength(e){
if(e.target.value.length === e.target.maxLength) {
e.stopPropagation();
e.preventDefault();
return false;
}
return true;
}

stopPropagation() is used to stop bubbling effect , i.e if a component has an event handler and its parent component also has an event handler then it stops the parent’s event handler to fire.

preventDefault() stops the event handler of the component on which it is applied and also stops default function of that element.

Bubbling effect is when an event happens on an element, it first runs the handlers on it, then on its parent, then all the way up on other ancestors.

Here we are not able to change the values as default action on input tag. Every key has a unique value and keyCode returns that value. First we will define values of keys we are going to use. In order to solve this we insert the below code in the checkLength() function.

const KEYS = {
leftKey: 37,
rightKey: 39,
backspace: 8,
deleteKey: 46,
};
if(e.keyCode === KEYS.backspace ||
e.keyCode === KEYS.deleteKey ||
e.keyCode === KEYS.rightKey ||
e.keyCode === KEYS.leftKey){
return true;
}

Till now this may seem to be working fine but if a user enters ‘e’ or ‘.’ this will break.

To solve this problem we need to add two checks and add two more values to KEYS

// add these values in KEYS....
digitZero: 48,
digitNine: 57
// update this if statement in checkLength() function...
if(e.keyCode < KEYS.digitZero ||
e.keyCode > KEYS.digitNine ||
e.target.value.length ===e.target.maxLength) {
e.stopPropagation();
e.preventDefault();
return false;
}

You can see the problem is still reflecting in mobile browsers as keyCode gives an undefined value. For mobile, keyCode is only useful if you want to use Enter or Backspace keys.

To solve this problem we will change the value of attribute type to “tel”. To remove special characters which “tel” type offers, we will add a function removeSpecialCharacters() to onKeyUp attribute. We can still see special characters on PC before onKeyUp is triggered. We will use event.shiftKey to remove this issue. So the <input> tag will be:

<input id="inputText" type="tel" 
pattern="[0-9]*"
maxLength="10"
onKeyDown={e=>this.checkLength(e)}
onKeyUp={removeSpecialCharacters}
/>

And the script will look something like:

removeSpecialCharacters = e => {
// replacing no's other than 0-9
e.target.value = e.target.value.replace(/[^0-9 ]/g, '');
// to replace special characters
e.target.value = e.target.value.replace(/[&\/\\#, +()$~%.'":*?<>
{}]/g, '');
};
checkLength(e){

const KEYS = {
leftKey: 37,
rightKey: 39,
backspace: 8,
deleteKey: 46,
digitZero: 48,
digitNine: 57
};
if (
e.keyCode === KEYS.backspace ||
e.keyCode === KEYS.deleteKey ||
e.keyCode === KEYS.rightKey ||
e.keyCode === KEYS.leftKey) {
return true;
}
if(e.keyCode < KEYS.digitZero ||
e.keyCode > KEYS.digitNine ||
e.target.value.length ===e.target.maxLength ||
e.shiftKey) {
e.stopPropagation();
e.preventDefault();
return false;
}
return true;
}

We can use this method to efficiently take the following inputs:

  • Mobile numbers
  • OTP
  • Credit/Debit Card Numbers

You can read more about new input types of HTML5 by clicking here.

--

--