简体   繁体   中英

Regex to allow only numbers and decimals not working in Javascript

I am trying this below code and the regex isn't working and it is allowing all the characters in the input box.

Desired: Input text box should not accept any other character other than numbers and decimal point.

<html>
<body>
    <input type="text" onkeypress="myfunction(event);"></input>
<script>
    function myfunction(e){
         var p = new RegExp(/^[0-9]+([.][0-9]+)?$/);
         return e.charCode === 0 ||   p.test(String.fromCharCode(e.charCode));      
    }
</script>
</body>
</html>

You are passing 1 char each time to the myfunction function, so you cannot check the whole value with /^[0-9]+([.][0-9]+)?$/ regex to make sure your format is adhered to.

Check if you input digits, or only allow typing a dot if there is no dot in the input field yet:

 <input type="text" id="test" onkeypress="return myfunction(event);" /> <script> function myfunction(e) { return e.charCode === 0 || ((e.charCode >= 48 && e.charCode <= 57) || (e.charCode == 46 && document.getElementById("test").value.indexOf('.') < 0)); } </script> 

Here's an alternative way. I'm using the oninput event that is triggered on every value change by user (not only key presses). I'm saving the last valid value and restoring it whenever the new value is invalid.

 <input type="text" id="test1" oninput="validateNumber(this);" /> <script> var validNumber = new RegExp(/^\\d*\\.?\\d*$/); var lastValid = document.getElementById("test1").value; function validateNumber(elem) { if (validNumber.test(elem.value)) { lastValid = elem.value; } else { elem.value = lastValid; } } </script> 

In contrast to most other answers here this works flawlessly with all input techniques like drag'n'drop, copy'n'paste etc. It also supports special control keys like Ctrl+a (for selecting contents), Pos1 , End and so on.

Should add a "return" prior to the function.

HTML:

<input type="text" value="" onkeypress="return myfunction(event)" />

JS:

function myfunction(e){
  var p = new RegExp(/^[0-9]+([.][0-9]+)?$/);
  return e.charCode === 0 || p.test(String.fromCharCode(e.charCode));
}

Regarding the Regex:

the problem with the regex is the the "." is a part of a subset that has a number after it. So: "5." is invalid but "5.3" is valid. However, the function runs for every key press!

So let's try to write: 5.3 which should be valid:

5 - valid

. - invalid

3 - valid

The solution would be to allow a "." on its own as long as it comes after a number.

After that another validation would have to occur in order to make sure that there are digits after the ".".

JSFIDDLE

Try to store the string in a "buffer":

<html>
<body>
    <input type="text" onkeypress="myfunction(event);"></input>
<script>
    var inputString = "";
    function myfunction(e){
         if (e.charCode === 0)
           return true;
         var p = new RegExp(/^[0-9]+([.][0-9]+)?$/);
         var testString = inputString + String.fromCharCode(e.charCode);
         if (p.test(testString))
           return true;
         inputString = testString;      
    }
</script>
</body>
</html>

Take with a bit of salt since I did not test it :)

You could also just read the contents of the input, but that is not necessarily pretty. On the other hand, with my solution you'll have trouble with stuff like backspaces or users clicking in the middle of the text and typing this way. This is just to make you aware of the limitations.

I modified @Wiktor Stribiżew Solution to allow insert from the clipboard and also make sure you and I can use this solution on multiple input elements without targeting one single element.

<input type="tel" onkeypress="return allowOnlyNumbers(event);" oninput="return allowOnlyNumbers(event);"/>

Things to note

  1. The [oninput] would help us with insert from the clipboard.

  2. The [onkeypress] would help us with single characters.

     function allowOnlyNumbers(e) { // on input if (e.inputType == "insertFromPaste") { var validNumber = new RegExp(/^\\d*\\.?\\d*$/); return (!validNumber.test(e.target.value) ? e.target.value = '' : e.target.value); } // on key press return e.charCode === 0 || ((e.charCode >= 48 && e.charCode <= 57) || (e.charCode == 46 && e.target.value.indexOf('.') < 0)); }

If you are using jquery you can do the following

let lastValid = $("#Control").val();
$('#Control').on('input', function () {
    var validNumber = new RegExp(/^\d*\.?\d*$/);
    var newValue = $(this).val();
    if (validNumber.test(newValue)) {
        lastValid = newValue;
    } else { $(this).val(lastValid); }
});

Here is my solution for StimulusJS and Rails. I have 2 different regexes for that. First of alle I check if the input is a decimal. I do it with this function which has support for German decimals:

export function decimalMatchFor( lang, value ) { 
  if (lang == null || lang == "") {
    return value.match(/^\d+\.\d{0,2}/igm);
  }

  if (lang == "de") {
    return value.match(/^\d+\,\d{0,2}/igm);
  } else if (lang == "en") {
    return value.match(/^\d+\.\d{0,2}/igm);
  } else {
    return value.match(/^\d+\.\d{0,2}/igm);
  }
}

In the Stimulus Controller I'm using this code:

let lang = document.documentElement.lang;
let cleaned = ""  
let numberMatch = this.duration_floatTarget.value.match(/^\d+/);
let decimalMatch = decimalMatchFor(lang, this.duration_floatTarget.value)
if (decimalMatch) {
  cleaned = decimalMatch[0]
} else if (numberMatch) {
  cleaned = numberMatch[0]
}
this.duration_floatTarget.value = cleaned;

That works pretty well for me.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM