← El DOM: la web que responde

Sesión 9 · Semana 3

Validación accesible

Hoy · Hoja de ruta

  1. 1. Aprende: Cómo se combina la validación nativa del navegador con la tuya, sin perder accesibilidad.
  2. 2. Haz: Valida tu formulario de contacto y muestra errores que se puedan oír.
  3. 3. Comprueba: Un lector de pantalla anuncia el error y el foco va al campo que falla.

Antes de empezar · 5 minutos, sin apuntes

  1. ¿Qué validación tiene ya tu formulario de la UD1, sin JavaScript?
  2. Un error escrito en rojo junto al campo, ¿lo percibe quien no ve la pantalla?
  3. ¿Por qué el servidor también tendrá que validar, en la UD6?

Lo que el navegador ya hace

En la UD1 escribiste campos obligatorios, tipos de dato y patrones. Eso sigue funcionando y es la primera línea de defensa. JavaScript no viene a sustituirla:

campo.validity.valueMissing;    // obligatorio y vacío
campo.validity.typeMismatch;    // no parece un correo
campo.validity.patternMismatch;
campo.checkValidity();          // true / false
formulario.noValidate = true;   // asumo yo la presentación de los errores

Tres validaciones, y ninguna sobra

  1. Nativa: inmediata y gratis, funciona sin JavaScript.
  2. Con JavaScript: mensajes mejores, reglas que el HTML no expresa, avisos mientras se escribe.
  3. En el servidor (UD6): la única obligatoria, porque las dos anteriores se pueden saltar.

Un cliente que valida bien mejora la experiencia. Un servidor que no valida es un agujero.

Un error que se ve y se oye

<label for="email">Correo electrónico</label>
<input type="email" id="email" name="email" required
       aria-describedby="error-email">
<p id="error-email" class="error" role="alert"></p>
function mostrarError(campo, mensaje) {
  const destino = document.querySelector(`#error-${campo.id}`);
  destino.textContent = mensaje;
  campo.setAttribute("aria-invalid", "true");
}

function limpiarError(campo) {
  document.querySelector(`#error-${campo.id}`).textContent = "";
  campo.removeAttribute("aria-invalid");
}

Tres piezas que hacen el error perceptible para todo el mundo: aria-describedby ata el mensaje al campo, aria-invalid marca el campo como erróneo, y role="alert" hace que el lector de pantalla lo anuncie al aparecer.

El color rojo, por sí solo, no informa a quien no distingue colores. Igual que en la UD2: el color acompaña, no comunica.

Cuándo avisar

Avisar con cada tecla mientras alguien escribe su correo es molesto y aparece en rojo antes de que haya terminado. El criterio habitual:

Cuándo se valida cada campo
  1. Al salir del campo: primera comprobación
  2. Al enviar: todos los campos
  3. Mientras se escribe: solo para quitar un error ya mostrado

Al enviar

formulario.addEventListener("submit", (evento) => {
  evento.preventDefault();
  const errores = validarContacto(Object.fromEntries(new FormData(formulario)));

  if (errores.length > 0) {
    errores.forEach(({ campo, mensaje }) => mostrarError(campos[campo], mensaje));
    campos[errores[0].campo].focus();     // el foco, al primero que falla
    return;
  }

  enviar();
});

Llevar el foco al primer campo con error es lo que permite corregir sin buscar. Y validarContacto es, otra vez, la función de validación de la UD3: recibe un objeto y devuelve la lista de errores.

Tarea 9 · Formulario validado

  1. Añade a cada campo su párrafo de error con role="alert" y aria-describedby.
  2. Valida al salir de cada campo y al enviar.
  3. Muestra todos los errores a la vez y lleva el foco al primero.
  4. Quita el error en cuanto el campo se corrige.
  5. Prueba el formulario solo con el teclado, de principio a fin.
  6. Comprueba que sin JavaScript el formulario sigue validando lo básico.
Objetivo mínimoErrores accesibles, foco al primero y sin recarga.
Si lo tienesAñade un resumen de errores al principio del formulario, con enlaces a cada campo.
RetoEscribe un mensaje distinto para «vacío» y para «formato incorrecto» en el mismo campo.

Cierre de la semana 3

  • Tu catálogo se genera desde datos y trata el caso vacío.
  • Lees el formulario y conviertes cada valor.
  • Los errores se ven, se oyen y llevan el foco donde toca.
  • La validación nativa sigue funcionando sin JavaScript.
Ver respuestas

1 · Nativa, en el cliente con JavaScript, y en el servidor; la del servidor es la obligatoria.

2 · aria-describedby, aria-invalid y role="alert".

3 · Al primer campo que falla, para poder corregir sin buscarlo.

Microprueba semanal 3 · 5–10 minutos

Individual, sin IA y sin apuntes.

  1. ¿Qué significa que un render sea idempotente, y qué se ve si no lo es?
  2. Escribe cómo leerías un campo numérico de formulario para poder sumarlo.
  3. Nombra los tres atributos que hacen que un error de formulario se perciba sin ver la pantalla.
---