javascripthtmlinputsrcmasking

Using this script on an input tag but it removes the entered text slightly after a letter is entered


function formatPhoneNumber(value) {
        if (!value) return value;
        const phoneNumber = value.replace(/[^\d]/g, '');
        const phoneNumberLength = phoneNumber.length;
        if (phoneNumberLength < 4) return phoneNumber;
        if (phoneNumberLength < 7) {
          return `(${phoneNumber.slice(0, 3)}) ${phoneNumber.slice(3)}`;
        }
        return `(${phoneNumber.slice(0, 3)}) ${phoneNumber.slice(
          3,
          6
        )}-${phoneNumber.slice(6, 9)}`;
      }

function phoneNumberFormatter() {
        const inputField = document.getElementById('phone-number');
        const formattedInputValue = formatPhoneNumber(inputField.value);
        inputField.value = formattedInputValue;
      }

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="home.css">
    
   
    <title>Document</title>
</head>
<body>
    
    <input onkeydown="phoneNumberFormatter()" id="phone-number" />

    




    <script src="home.js" type="text/javascript"></script>
  </body>
</html>

How can I fix the issue of when an user enters an incorrect type of input such as a letter for it to not be procceced and displayed on the input but instead ignore it until a number is to be entered.


Solution

  • You need to pass a keydown event object into your formatter and block that event if it contains a letter.

    For example, in your html:

    <input onkeydown="phoneNumberFormatter(this, event)" id="phone-number" />
    

    and then in your js:

    const MAX_LEN = 14;
    
    function isControl(value) {
      return value === 'LeftArrow' || value === 'RightArrow' || value === 'Backspace';
    }
    
    function isDigit(value) {
      return value >= '0' && value <= '9';
    }
    
    function formatPhoneNumber(value, event) {
      if ((!isDigit(event.key) && !isControl(event.key)) ||
        (isDigit(event.key) && value.length === MAX_LEN)) {
        event.preventDefault();
        return value;
      }
      console.log(value.length);
      if (!value) return value;
      const phoneNumber = value.replace(/[^\d]/g, '');
      const phoneNumberLength = phoneNumber.length;
      if (phoneNumberLength < 4) return phoneNumber;
      if (phoneNumberLength < 7) {
        return `(${phoneNumber.slice(0, 3)}) ${phoneNumber.slice(3)}`;
      }
      return `(${phoneNumber.slice(0, 3)}) ${phoneNumber.slice(
        3,
        6
      )}-${phoneNumber.slice(6, 9)}`;
    }
    
    function phoneNumberFormatter(event) {
      const inputField = document.getElementById('phone-number');
      const formattedInputValue = formatPhoneNumber(inputField.value, event);
      inputField.value = formattedInputValue;
    }
    

    This approach will allow you to block the incoming keydown event and prevent input from showing it.

    Please let me know if this helps.