skip to Main Content

I have an input field. I need the input to have the following format: AC-123456789
When I input the characters in the field, after the second character I want the system to add the hyphen automatically just once. The first group of characters has to be a specific letter for the first character and any letter or number for the second character. The second group can only be numbers. If I want to delete using backspace, I should be able to delete also the hyphen.
So far I have:

const transformInput = (input) => {
  const inputLength = input.replace('-', '').length;
  if (inputLength > 1 &&  input[2] !== '-') input = `${input.slice(0,2)}-${input.slice(2)}`;
  else if (inputLength === 2 && input[2] === '-') input = input.slice(0,2);
  return input
}

The problem with the above code is that if I have ‘AB-‘ and I delete with backspace, it won’t delete. I have to add a number like ‘AB-2’ and then it will delete leaving me with ‘AB’. How can the above be improved? Is there an easier way to do it in regex?

I tried using regex as follows but have not been succefull:

const transformInput = (input) => {
  return input.replace(/(d[A-Z0-9]{2})(d{1-9})/, '$1-$2')
}

Thanks

2

Answers


  1. This seems to cover most cases

    Have to save the last keystroke if you want to magically remove the - when appropriate

    It could do with a little more work to handle where the caret is so it doesn’t keep jumping to the end

    let lastKey = null;
    const transformInput = (input) => {
      const inputLength = input.length;
      const nodash = input.replaceAll('-', '');
      const hasDash = input.includes('-');
      if (inputLength < 3 && lastKey === 'Backspace') {
        return nodash.slice(0,2);
      }
      if (inputLength > 2) {
        if (nodash.length > 2) {
          return `${nodash.slice(0,2)}-${nodash.slice(2)}`;
        }
        return nodash;
      }
      return input
    }
    const input = document.querySelector('input');
    input.addEventListener('input', () => {
      input.value = transformInput(input.value);
    })
    input.addEventListener('keydown', (e) => {
      lastKey = e.key;
    })
    <input>
    Login or Signup to reply.
  2. Here’s a solution using regex, it allows you to type only valid pattern:

    document.querySelector('input').addEventListener('input', e => {
      e.target.value = e.target.value.replace(
        /^([a-z0-9]{1,2})((?<=..)-)?(d{1,9})?.*|.+/i, 
        (_, $1 = '', $2 = '', $3 = '') => ($2 || $3 ? `${$1}-${$3}` : $1).toUpperCase()
      );
    });
    <input>

    The substitution pattern is a little bit more complex than the pattern for validation (/^[0-9A-Z]{2}-d{9}$/).

    • regex
    ^                 # beggining of the input
    ([a-z0-9]{1,2})   # 1 or 2 alphanumerics, put in group $1
    ((?<=..)-)?       # an optional hyphen, but only register it when it is preceded by at least two characters, group $2
    (d{1,9})?        # 1 to 9 digits, optional, group $3
    .*                # anything after this pattern that needs the be discarded
    |                 # if the previous pattern doesn't match
    .+                # then discard everything
    
    • substitution function
    // if the hyphen ($2) or following digits ($3) is captured, transform it into `AA-0123456789` format
    // otherwise only keep the first part
    (_, $1 = '', $2 = '', $3 = '') => ($2 || $3 ? `${$1}-${$3}` : $1).toUpperCase()
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search