Crear una máscara de números en un input con Javascript

Crear una máscara de números en un input con Javascript

En este artículo vamos a aprender a hacer una máscara en un campo de texto, para la introducción de números y que al usuario le aparezcan con un formato específico, que podemos configurar nosotros mismos por medio de un patrón. Es una práctica de Javascript para realizar lo que se llama una «máscara» de un número.

No es un ejercicio trivial y requiere varias etapas para construirlo, pero vamos a intentar verlas de modo que se expliquen en líneas generales cómo conseguir ese efecto de máscara numérica en un campo input de formulario. Además, compartiremos un componente, web component estándar, para poder crear un campo input con una máscara configurable sin necesidad de programación.

Resumen del flujo para implementar una máscara en un campo input

Explico primero en líneas generales el enfoque que vamos a seguir para realizar este problema. Se trata de implementar un campo input normal, en el que vamos a detectar eventos de teclado.

Asociaremos al campo input un manejador para el evento de teclado «keydown» que bloqueará la escritura de texto en el campo. En vez de escribir el texto directamente lo que haremos será procesarlo, que básicamente consiste en:

  • Comprobar si es un carácter válido.
  • Si no es valido no hago nada.
  • Si es válido lo meto en una variable interna de mi programa que concatena todos los caracteres válidos introducidos.
  • Por último, cada vez que se introduce un nuevo carácter válido, le aplico la máscara y actualizo el campo de texto para mostrar el número con su correspondiente máscara.

Implementar la máscara numérica como un web component

Todo eso lo vamos a ver ahora con código, pero por si a alguien le interesa poder hacer una máscara sin necesidad de programar, he creado un web component que hace todo el trabajo automáticamente, sin tener que escribir una línea de código.

Sería tan sencillo como colocar esta etiqueta:

<dile-input-number-mask label="Teléfono" placeholder="Indica tu teléfono" mask="000-00 00 00"></dile-input-number-mask>

El patrón introducido lo colocas en el atributo «mask» y simplemente escribirá el teléfono tal cual se indica en el patrón.

Cómo se codifica el patrón de la máscara

En el patrón todo valor numérico a introducir se indica como un «0» y todo valor que no sea un cero formaría parte de la máscara. Por tanto el número «600123123» aparecería escrito en el campo de texto como «600-12 31 23».

Puedes ver la documentación del componente de máscara en este enlace.

Implementar la máscara de números con nuestro propio Javascript

Ahora vamos a explicar cómo realizar esta máscara de números en un campo input con un código sencillo en nuestro proyecto con Javascript.

Comenzamos con un campo input al que hemos colocado un identificador, para luego referirnos a él con Javascript.

<form>
    <input type="text" id="elinput">
</form>

Ya en Javascript, indicamos el código necesario para aplicarle la máscara a ese campo input, con este código.

document.addEventListener('DOMContentLoaded', function() {
  applyInputMask('elinput', '0--0*0 000_000');
});

Simplemente estamos invocando una función applyInputMask() que se encargará de todo, a la que le pasamos el identificador (id) del campo input y el patrón de la máscara que deseamos.

Antes ya explicamos la sintaxis del patrón. En este caso el valor «123456789» aparecería en el campo como «1–2*3 456_789». Como ves, puedes indicarle un patrón todo lo complejo que quieras.

La función applyInputMask() tendría esta forma:

function applyInputMask(elementId, mask) {
  let inputElement = document.getElementById(elementId);
  let content = '';
  let maxChars = numberCharactersPattern(mask);
  
  inputElement.addEventListener('keydown', function(e) {
    e.preventDefault();
    if (isNumeric(e.key) && content.length < maxChars) {
      content += e.key;
    }
    if(e.keyCode == 8) {
      if(content.length > 0) {
        content = content.substr(0, content.length - 1);
      }
    }
    inputElement.value = maskIt('0--0*0 000_000', content);
  })
}

Básicamente hace toda la operativa que habíamos resumido antes, capturar los eventos de teclado, evitando que se escriba en el campo de texto, sino que almacena los caracteres válidos en una variable y hace el cambio del value del campo de texto una vez ha convertido el valor introducido hasta el momento en su representación una vez aplicada la máscara.

Para ello está accediendo al campo de texto y creando un par de variables locales:

  • «content» mantiene una representación interna de todo lo que el usuario va introduciendo, antes de aplicarle la máscara.
  • «maxChars» mantiene el número de caracteres máximo que permitiría el patrón.

Ya en el código del manejador de evento ‘keydown’ realizamos un par de acciones.

Primero comprobamos que el valor introducido es un número (de cero a 9) y que hay espacio suficiente para añadir ese número atendiendo al patrón. En ese caso almacenamos el carácter introducido dentro de la variable content.

Segundo, comprobamos si se ha pulsado la tecla de borrado (backspace, con keyCode 8), en cuyo caso, si había algo escrito, se elimina el último carácter introducido.

Por último se actualiza el value del campo input, colocando el valor, una vez aplicada la máscara.

Funciones de apoyo

El código anterior se apoya en estas otras funciones para realizar su tarea.

Esta función simplemente dice si un caracter introducido es numérico.

function isNumeric(char) {
  return !isNaN(char - parseInt(char));
}

Ahora veremos la función que se encarga de aplicar la máscara. Es un poco compleja, pero básicamente realiza un recorrido conjunto al patrón y al valor al que aplicar la máscara.

Hace el bucle hasta que se llega al final del patrón o al final del valor a aplicar la máscara. Por ello tenemos dos situaciones de salida, que podemos evaluarlos con las variables locales «position» (que es la posición en el patrón) y «currentChar» (que es la posición en el valor que tenemos que aplicar la máscara con Javascript).

En cada iteración va tomando un carácter del patrón o un carácter de la máscara, según toca. La decisión de tomar el carácter de un lugar o de otro la toma analizando el patrón y comprobando si en el patrón se encuentra un «0» o cualquier otro carácter. La cadena, una vez aplicada la máscara, se va almacenando en la variable local «masked».

function maskIt(pattern, value) {
  let position = 0;
  let currentChar = 0;
  let masked = '';
  while(position < pattern.length && currentChar < value.length) {
    if(pattern[position] === '0') {
      masked += value[currentChar];
      currentChar++;
    } else {
      masked += pattern[position];
    }
    position++;
  }
  return masked;
}

Quizás la función anterior sea la más compleja de este ejercicio. Tómate tu tiempo para examinarla y espero que la puedas entender.

Ahora veremos la última función, que se encarga de saber el número de caracteres máximo que permitiría un patrón. Para eso hace simplemente un recorrido al patrón y cuenta las veces que aparece el carácter «0».

function numberCharactersPattern(pattern) {
  let numberChars = 0;
  for(let i = 0; i < pattern.length; i++) {
    if(pattern[i] === '0') {
      numberChars ++;
    }
  }
  return numberChars;
}

Con esto hemos terminado esta práctica, que espero que os haya resultado de utilidad y os sirva para implementar la máscara numérica con Javascript en cualquier aplicación, ya sea implementando vuestro propio código Javascript o con el web component que os hemos compartido.

Otras entradas que pueden interesarte

Mauricio Valderrama Escrito por:

2 comentarios

  1. Julian
    21 mayo, 2021
    Responder

    Muy buena información, gracias.

  2. Laura
    21 mayo, 2021
    Responder

    Genial gracias por este consejo.

Responder a Julian Cancelar la respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *