Revisando el formulario para registrar aliados en mi CRM, escribí luis web! en el campo del código de referido. Ese campo solo debía aceptar minúsculas, números y guion. Aun así, el formulario lo dejó pasar sin marcar nada.
No se coló nada raro: el servidor también validaba el código y respondió con un error 400. Pero el formulario tenía que haberlo frenado antes, y no lo hizo. Nadie había tocado ese campo.
Qué pasó
El campo tenía esta validación:
<input pattern="[a-z0-9-]{3,24}">
Ese patrón funcionó durante años. Pero a mediados de 2023 cambió el estándar de HTML: el navegador ya no compila pattern con la bandera u, sino con la bandera v de las expresiones regulares (en JavaScript se llama unicodeSets).
La bandera v trae cosas nuevas dentro de los corchetes, como la intersección y la resta de conjuntos. A cambio, es más estricta: varios signos que antes podías poner tal cual dentro de [ ] ahora necesitan una diagonal invertida (\) antes. El guion es uno de ellos.
Y aquí está la trampa: cuando el patrón no es válido, el navegador no te avisa en pantalla. Simplemente se salta la validación y acepta cualquier texto. Lo único que deja es un error en la consola. En Chrome se ve así:
Pattern attribute value [a-z0-9-]{3,24} is not a valid regular expression: ... Invalid regular expression: /[a-z0-9-]{3,24}/v: Invalid character class
El arreglo
Ponle una diagonal invertida antes al guion:
<input pattern="[a-z0-9\-]{3,24}">
Con eso, luis web! ya no pasa y luis-web sí.
Ojo si el patrón vive en JavaScript
En mi CRM el patrón está en una constante de JavaScript, y ahí hay otra trampa: entre comillas, '\-' se convierte en - y la diagonal desaparece sin avisar. Necesitas dos:
const ALLY_CODE_PATTERN = '[a-z0-9\\-]{3,24}'
O usa String.raw`[a-z0-9\-]{3,24}`, que deja la diagonal tal cual. Si lo escribes directo en el atributo de JSX (pattern="..."), basta con una, igual que en HTML.
La lista: qué lleva diagonal invertida dentro de [ ]
Con la bandera v, estos 10 caracteres necesitan \ antes cuando los quieres como texto dentro de los corchetes:
( ) [ ] { } / - | \
Es decir: paréntesis, corchetes, llaves, diagonal, guion, barra vertical y la misma diagonal invertida.
Tampoco se valen ciertos signos repetidos seguidos dentro de los corchetes, porque la bandera v los reserva:
.. !! ## $$ %% ** ++ ,, :: ;; << == >> ?? @@ ^^ `` ~~
El && sí se puede usar, pero ya no significa «dos ampersands»: significa intersección.
Y no pongas diagonales de más: \" y \' dentro de los corchetes también rompen el patrón. Las comillas van solas.
Patrones comunes que se rompen
Código o usuario: [a-z0-9-]{3,24} → [a-z0-9\-]{3,24}
Correo: [\w.+-]+@[\w-]+\.[a-z]{2,} → [\w.+\-]+@[\w\-]+\.[a-z]{2,}
Teléfono: [0-9()+ ]{10,15} → [0-9\(\)+ ]{10,15}
El punto y el signo de más sueltos dentro de los corchetes siguen funcionando; el problema es el guion y los paréntesis.
Cómo revisar tu proyecto en 5 minutos
- Busca
pattern= en tu código. No olvides las constantes que pasas como pattern={...}. - Revisa si algún patrón trae, dentro de
[ ], un carácter de la lista sin \ antes. - Abre cada formulario con la consola del navegador abierta y escribe algo en cada campo: si un patrón no compila, aparece un error que empieza con «Pattern attribute value».
- Para probar un patrón suelto, pégalo en la consola como literal con la bandera
v: /[a-z0-9-]{3,24}/v. Si responde «Invalid character class», hay que arreglarlo.
La lección
La validación del navegador es comodidad para quien llena el formulario. La del servidor es la que manda.
Un cambio en el estándar, sin que yo tocara una línea, apagó la validación del formulario. Si mi API no hubiera validado el código, ese luis web! se habría guardado tal cual. Por eso valido dos veces: en el navegador, para que llenar el formulario sea rápido, y en el servidor, para que los datos siempre estén bien.
¿Te sirvió?
En mi TikTok comparto lo que reviso en mis proyectos, con la serie «Así lo resolví». Y si tienes una página o un sistema con formularios y no sabes si siguen validando bien, en JoniTech lo revisamos en un diagnóstico digital gratis.
Fuentes
MDN: el atributo pattern
WHATWG: el cambio a la bandera v
V8: la bandera v en las expresiones regulares