Formularios con JavaScript
En esta lección
Los formularios son la forma principal en que una persona le da datos a tu aplicación. Con JavaScript puedes leer esos datos, comprobarlos mientras se escriben y enviarlos sin recargar la página.
Leer el valor de un campo
const email = document.querySelector("#email").value; // texto
const edad = Number(document.querySelector("#edad").value); // ¡conviértelo!
const acepta = document.querySelector("#acepto").checked; // true / false
const ciudad = document.querySelector("#ciudad").value; // valor del <option> elegido
.valuesiempre es texto, incluso en un<input type="number">. Convierte conNumber()cuando necesites un número (y recuerda que un campo vacío se convierte en0).- En casillas (
checkbox) y botones de opción (radio), lo que importa es.checked.
¿Qué radio está marcado?
Los radios de un mismo grupo comparten name. Con el selector de atributo y la pseudoclase :checked obtienes el elegido:
const plan = document.querySelector("input[name=plan]:checked")?.value;
El ?. evita un error si no hay ninguno marcado. Para varias casillas marcadas:
const intereses = [...document.querySelectorAll("input[name=interes]:checked")]
.map((casilla) => casilla.value);
Todo el formulario de una vez: FormData
En lugar de leer los campos uno a uno, FormData recoge todos los que tienen name:
formulario.addEventListener("submit", (evento) => {
evento.preventDefault();
const datos = new FormData(formulario);
datos.get("email"); // el valor de un campo
datos.getAll("interes"); // todos los valores de un grupo de casillas
const objeto = Object.fromEntries(datos); // { email: "...", plan: "pro", ... }
});
Object.fromEntries lo convierte en un objeto normal, listo para validarlo o enviarlo al servidor como JSON.
Los eventos de un formulario
| Evento | Cuándo se dispara | Úsalo para |
|---|---|---|
input | Con cada cambio del valor (cada tecla, pegar, borrar…) | Validar o actualizar algo en tiempo real |
change | Cuando el usuario termina de cambiar el valor (sale del campo, elige una opción, marca una casilla) | Reaccionar a una decisión |
submit | Al enviar el formulario (botón o tecla Enter) | Validar todo y enviar |
focus / blur | Al entrar / salir de un campo | Mostrar ayudas |
reset | Al vaciar el formulario | Restablecer mensajes |
Antiguamente se combinaban keyup, paste y mouseup para detectar cambios mientras se escribe. El evento input lo cubre todo de una vez: cualquier forma de cambiar el texto.
Recuerda que los eventos suben: si escuchas change en el formulario, te enteras de los cambios de todos sus campos con un solo manejador.
Validar
Validar es comprobar que los datos tienen sentido antes de usarlos. Primero, aprovecha lo que HTML ya hace solo (required, type="email", min, pattern…). Después, añade con JavaScript las reglas que HTML no puede expresar.
Siguiendo la idea de separar lógica e interfaz, la regla de validación va en su propia función, que no sabe nada de la página:
// Lógica: recibe un valor y devuelve un mensaje de error (o "" si está bien)
function validarUsuario(usuario) {
if (usuario.trim().length < 3) return "El usuario debe tener al menos 3 caracteres";
if (!/^[a-z0-9_]+$/i.test(usuario)) return "Solo letras, números y guiones bajos";
return "";
}
// Interfaz: lee el campo, llama a la lógica y muestra el resultado
campoUsuario.addEventListener("input", () => {
const error = validarUsuario(campoUsuario.value);
mensajeUsuario.textContent = error;
campoUsuario.setAttribute("aria-invalid", error ? "true" : "false");
});
/^[a-z0-9_]+$/i es una expresión regular: un patrón para comprobar textos. .test(texto) devuelve true si el texto lo cumple.
Mensajes de error accesibles
- Pon el mensaje junto al campo, no en una alerta.
- Relaciónalo con el campo con
aria-describedby, y marca el campo conaria-invalid="true". Así los lectores de pantalla lo anuncian. - No uses solo el color rojo: acompáñalo de texto.
- No valides mientras la persona aún está escribiendo por primera vez (es molesto ver “email no válido” tras la primera letra). Una buena regla: valida al salir del campo (
blurochange) y, si ya había un error, vuelve a validar en cadainputpara que desaparezca en cuanto se corrija.
<input id="usuario" aria-describedby="error-usuario">
<p id="error-usuario" class="error" aria-live="polite"></p>
La validación del navegador desde JavaScript
Cada campo sabe si cumple sus reglas HTML:
campo.checkValidity(); // true o false
campo.validationMessage; // el mensaje del navegador
campo.setCustomValidity("Este usuario ya existe"); // mensaje propio ("" para quitarlo)
formulario.reportValidity(); // muestra los mensajes del navegador
Si prefieres mostrar tus propios mensajes en lugar de las burbujas del navegador, añade novalidate al <form> y encárgate tú de todo en el submit.
Al enviar
formulario.addEventListener("submit", async (evento) => {
evento.preventDefault();
const datos = Object.fromEntries(new FormData(formulario));
const errores = validarTodo(datos);
if (errores.length > 0) {
mostrarErrores(errores);
return;
}
boton.disabled = true; // evita envíos dobles
await enviarAlServidor(datos); // lo verás en la lección de fetch
boton.disabled = false;
formulario.reset();
});
La validación en el navegador es para ayudar al usuario, no es seguridad. Cualquiera puede desactivar JavaScript o enviar datos directamente a tu servidor sin pasar por el formulario. El servidor siempre tiene que volver a comprobarlo todo.
Pruébalo tú
Cambia el código y pulsa Ejecutar (o Ctrl + Enter).
Pon a prueba lo que has aprendido
¿Te ha quedado claro? Márcala y verás tu progreso en el explorador.