Search code examples
javascriptregexvalidationsanitizationhtml-input

How to make a text-type input-element accept just a numerical value (decimal, positive and negative) by ignoring invalid characters on each keypress?


I have an HTML input and this input just accept the string of number character,

Example:

input value: +0123.534534 or -234234.543345 or -13453, these input values are valid. The characters + or - just exist one and at first position in string value

I want every typing character the input value should keep the current valid string and replace the invalid input character with an empty character

Example:

When I typed : +123.g ==> the value should replace immediately +123. Or when I typed: g ==> the value should replace immediately with an empty value.

I found an implementation with this, but It lack of (+/-/.) character

const getDigitsOnly = (value) => String(value).replace(NOT_NUMBERS, '');

Solution

  • Here is my solution for it.

    We add an input event listener to the input box and for every input we format the entire input value.

    Note: Don't forget to trim trailing decimal point (e.g. "123." to "123") if exists when submitting the value.

    const inputBox = document.getElementById("inputBox");
    
    inputBox.addEventListener("input", () => {
      inputBox.value = format(inputBox.value);
    });
    
    function format(str) {
      if (!str.length) return str;
    
      str = str.replace(/[^.+-\d]/g, "");
      const firstChar = str.charAt(0);
      str = str.slice(1).replace(/[+-]/g, "");
    
      // Bug fix. Credit goes to @Peter Seliger
      // For pointing out the bug
      const charArray = [];
      let hasDecimalPoint = false;
    
      if (firstChar === ".") {
        if (!str.includes(".")) {
          hasDecimalPoint = true;
          charArray.push("0.");
        }
      } else charArray.push(firstChar);
      // End bug fix
    
      for (let i = 0; i < str.length; i++) {
        const char = str.charAt(i);
    
        if (char === ".") {
          if (hasDecimalPoint) continue;
          if (!i && firstChar !== "0") charArray.push("0");
          hasDecimalPoint = true;
        }
    
        charArray.push(char);
      }
    
      return charArray.join("");
    }
    <p>Enter your number here</p>
    <input id="inputBox" type="text" />

    The algorithm of the format function.

    1: If the input is empty then return the input
    2: Remove all characters except "-", "+", "." and digits
    3: Store the first character in a variable
    4: Remove all "+" and "-" (if exists) after the first character
    5: if the first character is "." then replace it with "0."
    6. Finally remove any duplicate decimal point (".") if exists
    

    And here are some dummy data to test the format function

    const dummyData = [
      "",
      "+",
      "-",
      ".",
      ".123",
      "+.123",
      "123.3.23",
      "12sfdlj3lfs.s++d_f",
      "12--++.123",
    ];