Prevent typing non-numeric in input type number

JavascriptHtml

Javascript Problem Overview


Using <input type=number> will cause this.value inside of an event listener to return an empty string if the input is not a valid number. You can see an example of this at http://jsfiddle.net/fSy53/

However, the invalid characters are still displayed in the input.

Is there any way to get the value that is actually displayed, including the invalid characters, from within an event listener?

My ultimate goal is to prevent users from actually typing any non-numeric characters into the field. I need to use type=number so that the numeric virtual keyboard is used by mobile devices. My goal would be to do something like this.value = this.value.replace(/[^0-9.]/g, "") on keyup keypress, but this doesn't work because if an invalid character is typed, reading from this.value returns "".

Javascript Solutions


Solution 1 - Javascript

Try preventing the default behaviour if you don't like the incoming key value:

document.querySelector("input").addEventListener("keypress", function (evt) {
    if (evt.which < 48 || evt.which > 57)
    {
        evt.preventDefault();
    }
});

Solution 2 - Javascript

You can accomplish this by preventing the keyPress event from occurring for non-numeric values

e.g (using jQuery)

$('.input-selector').on('keypress', function(e){
  return e.metaKey || // cmd/ctrl
    e.which <= 0 || // arrow keys
    e.which == 8 || // delete key
    /[0-9]/.test(String.fromCharCode(e.which)); // numbers
})

This accounts for all different types of input (e.g. input from the number pad has different codes than the keyboard) as well as backspace, arrow keys, control/cmd + r to reload etc

Solution 3 - Javascript

Please note that e.which, e.keyCode and e.charCode are deprecated: https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/which

I prefer e.key:

document.querySelector("input").addEventListener("keypress", function (e) {
	var allowedChars = '0123456789.';
	function contains(stringValue, charValue) {
        return stringValue.indexOf(charValue) > -1;
    }
    var invalidKey = e.key.length === 1 && !contains(allowedChars, e.key)
			|| e.key === '.' && contains(e.target.value, '.');
	invalidKey && e.preventDefault();});

This function doesn't interfere with control codes in Firefox (Backspace, Tab, etc) by checking the string length: e.key.length === 1.

It also prevents duplicate dots at the beginning and between the digits: e.key === '.' && contains(e.target.value, '.')

Unfortunately, it doesn't prevent multiple dots at the end: 234....

It seems there is no way to cope with it.

Solution 4 - Javascript

The other answers seemed more complicated than necessary so I adapted their answers to this short and sweet function.

function allowOnlyNumbers(event) {
  if (event.key.length === 1 && /\D/.test(event.key)) {
    event.preventDefault();
  }
}

It won't do change the behavior of any arrow, enter, shift, ctrl or tab keys because the length of the key property for those events is longer than a single character. It also uses a simple regular expressions to look for any non digit character.

Solution 5 - Javascript

inputs[5].addEventListener('keydown', enterNumbers);

function enterNumbers(event) {
  if ((event.code == 'ArrowLeft') || (event.code == 'ArrowRight') ||
     (event.code == 'ArrowUp') || (event.code == 'ArrowDown') || 
     (event.code == 'Delete') || (event.code == 'Backspace')) {
     return;
  } else if (event.key.search(/\d/) == -1) {
    event.preventDefault();
  }
}

in this case, the value of the input field stays intact when a non-number button is pressed, and still delete, backspace, arrowup-down-left-right work properly and can be used for modifying the digital input.

Solution 6 - Javascript

This solution seems to be working well for me. It builds on @pavok's solution by preserving ctrl key commands.

document.querySelector("input").addEventListener("keypress", function (e) {
  if (
    e.key.length === 1 && e.key !== '.' && isNaN(e.key) && !e.ctrlKey || 
    e.key === '.' && e.target.value.toString().indexOf('.') > -1
  ) {
    e.preventDefault();
  }
});

Solution 7 - Javascript

Update on the accepted answer:

Because of many properties becoming deprecated

> (property) KeyboardEvent.which: number @deprecated

you should just rely on the key property and create the rest of the logic by yourself:

The code allows Enter, Backspace and all numbers [0-9], every other character is disallowed.

document.querySelector("input").addEventListener("keypress", ({ key, preventDefault }) => {
  if (isNaN(parseInt(key, 10)) && !['Backspace', 'Enter'].includes(key)) {
      preventDefault();
    }
});

NOTE This will disable paste action

Solution 8 - Javascript

try this one :

  1. current key pressed -> e
  2. if e is not a number -> isNaN(e.key)
  3. when condition is true , so default action should not be taken as it normally would be -> e.preventDefault()
  4. else, return default action... e
input.addEventListener("keypress", function (e) {
  if (isNaN(e.key)) e.preventDefault();
});

Solution 9 - Javascript

I will add MetaKey as well, as I am using MacOS

input.addEventListener("keypress", (e) => {
    const key = e.key;
    if (!(e.metaKey || e.ctrlKey) && key.length === 1 && !/\d\./.test(key)) {
        e.preventDefault();
    }
}

Or, you can try !isNaN(parseFloat(key))

Solution 10 - Javascript

Based on Nrzonline's answer: I fixed the problem of the multiple "." at the end of the input by adding a

let lastCharacterEntered

outside of the input and then onKeyPress

e => {
          var allowedChars = "0123456789.";
          function contains(stringValue, charValue) {
            return stringValue.indexOf(charValue) > -1;
          }
          var invalidKey =
            (e.key.length === 1 && !contains(allowedChars, e.key)) ||
            (e.key === "." && contains(e.target.value, "."));
          console.log(e.target.value);
          invalidKey && e.preventDefault();
          if (!invalidKey) {
            if (lastCharacterEntered === "." && e.key === ".") {
              e.preventDefault();
            } else {
              lastCharacterEntered = e.key;
            }
          }
        }

Solution 11 - Javascript

I just had the same problem and discovered an alternative solution using the validation API - works without black magic in all major browsers (Chrome, Firefox, Safari) except IE. This solution simply prevents users from entering invalid values. I also included a fallback for IE, which is not nice but works at least.

Context: onInput function is called on input events, setInputValue is used to set the value of the input element, previousInputValue contains the last valid input value (updated in setInputValue calls).

    function onInput (event) {
        const inputValue = event.target.value;

        // badInput supported on validation api (except IE)
        // in IE it will be undefined, so we need strict value check
        const badInput = event.target.validity.badInput;

        // simply prevent modifying the value
        if (badInput === true) {
        // it's still possible to enter invalid values in an empty input, so we'll need this trick to prevent that
            if (previousInputValue === '') {
                setInputValue(' ');
                setTimeout(() => {
                    setInputValue('');
                }, 1);
            }
            return;
        }

        if (badInput === false) {
            setInputValue(inputValue);
            return;
        }

        // fallback case for IE and other abominations

        // remove everything from the string expect numbers, point and comma
        // replace comma with points (parseFloat works only with points)
        let stringVal = String(inputValue)
            .replace(/([^0-9.,])/g, '')
            .replace(/,/g, '.');

        // remove all but first point
        const pointIndex = stringVal.indexOf('.');
        if (pointIndex !== -1) {
            const pointAndBefore = stringVal.substring(0, pointIndex + 1);
            const afterPoint = stringVal.substring(pointIndex + 1);

            // removing all points after the first
            stringVal = `${pointAndBefore}${afterPoint.replace(/\./g, '')}`;
        }

        const float = parseFloat(stringVal);
        if (isNaN(float)) {
            // fallback to emptying the input if anything goes south
            setInputValue('');
            return;
        }
        setInputValue(stringVal);
}

Solution 12 - Javascript

Prevent typing non-Alphabet in specific input id for pages that have more than one input item.it's usable for Oracle Apex developers --- Append in HTML header of page

<script type="text/javascript">
function validateNumber(event) {
  const activeElmnt = document.activeElement;  
  var keyCode = event.keyCode;
  var excludedKeys = [8, 37, 39, 46];
 
   if ( activeElmnt.id == "input id in HTML page"){
        if (!((keyCode >= 65 && keyCode <= 90) ||
            (keyCode >= 97 && keyCode <= 122) ||
            (excludedKeys.includes(keyCode)))) {
            console.log("alphabets are not allowed");
            event.preventDefault();

  }
}
  console.log("keycode: " + keyCode + "ActiveElemet: "+activeElmnt.id);
}
</script>

-- Append in page HTML Body attribute onkeydown="validateNumber(event);"

Solution 13 - Javascript

here is my simple solution simply in this solution u should keep the input type to text so when you use event.target.value you get the full string not only the numbers or an empty string instead so you actually can check if there is a point yet or not. and i didn't use the deprecated properties event.which

isNumber(event) {
      var allowed = "";
      if (event.target.value.includes(".")) {
        allowed = "123456789";
      } else {
        allowed = "123456789.";
      }
      if (!allowed.includes(event.key)) {
        event.preventDefault();
      }
    }

document.getElementById('number').addEventListener('keypress', isNumber);

the HTML 



<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-js -->

     function isNumber(event) {
          var allowed = "";
          if (event.target.value.includes(".")) {
            allowed = "0123456789";
          } else {
            allowed = "0123456789.";
          }
          if (!allowed.includes(event.key)) {
            event.preventDefault();
          }
          }
          
          document.getElementById('number').addEventListener('keypress',isNumber);

<!-- language: lang-html -->

    <h3>You can input only numbers and one point (this would be a float or int) </h3>
    <input type="text" id="number" />

<!-- end snippet -->

Solution 14 - Javascript

A very nice react solution... You just want to consume the event if its NaN

    onKeyedPress = (e) => {
            if(!parseInt(e.key)){
                e.preventDefault();
            }
         }   

Solution 15 - Javascript

Try it:

document.querySelector("input").addEventListener("keyup", function () {
   this.value = this.value.replace(/\D/, "")
});

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
QuestionExplosion PillsView Question on Stackoverflow
Solution 1 - JavascriptGlenn LaneView Answer on Stackoverflow
Solution 2 - JavascriptdlangevinView Answer on Stackoverflow
Solution 3 - JavascriptpavokView Answer on Stackoverflow
Solution 4 - JavascriptKenCorbettJrView Answer on Stackoverflow
Solution 5 - JavascriptFevralleView Answer on Stackoverflow
Solution 6 - JavascriptpigeontoeView Answer on Stackoverflow
Solution 7 - JavascriptEugen SunicView Answer on Stackoverflow
Solution 8 - Javascriptfarid teymouriView Answer on Stackoverflow
Solution 9 - JavascriptPolvView Answer on Stackoverflow
Solution 10 - JavascriptChajiaView Answer on Stackoverflow
Solution 11 - JavascriptÁbel ÉnekesView Answer on Stackoverflow
Solution 12 - JavascriptZASA82View Answer on Stackoverflow
Solution 13 - Javascriptabdeslam chettoutView Answer on Stackoverflow
Solution 14 - JavascriptaustBrinkView Answer on Stackoverflow
Solution 15 - JavascriptDukeView Answer on Stackoverflow