Domina el flujo completo de un formulario en JavaScript: evita recargas con event.preventDefault(), captura datos con FormData, persiste un objeto con JSON en localStorage y renderiza el último mensaje guardado en la interfaz. Todo con buenas prácticas de DOM, nombres coherentes y una UX fluida.
¿Cómo preparar el HTML y evitar errores al copiar y pegar?
Antes de empezar, crea una carpeta nueva llamada Form y separa tu trabajo anterior del DOM para conservar el historial. Copia index.html y app.js, pero verifica que las rutas y los IDs coincidan para no heredar errores silenciosos por copiar y pegar.
- Crea la sección del formulario antes del cierre de main.
- Usa un ID claro para el formulario: por ejemplo, id="contact-form".
- Define atributos name coherentes: name para el input de nombre y message para el textarea.
- Agrega un botón con type="submit".
- Aplica estilos al final del archivo de estilos, con una clase hidden para ocultar bloques hasta mostrarlos.
- Valida en el navegador con Live Server que la interfaz cargue y que el envío no haga nada todavía.
Ejemplo mínimo de estructura HTML del formulario:
<section>
<form id="contact-form">
<label>
<span>Nombre</span>
<input name="name" type="text" />
</label>
<label>
<span>Mensaje</span>
<textarea name="message"></textarea>
</label>
<button type="submit">Enviar</button>
</form>
<div id="mensaje-guardado" class="hidden"></div>
</section>
Clave: el atributo name es lo que la API de FormData utiliza para extraer valores. Si cambias name en HTML, actualiza las lecturas en JavaScript.
¿Cómo manejar el submit con event.preventDefault y FormData?
El patrón base de formularios en JavaScript es simple: escuchar el submit, prevenir el comportamiento por defecto y leer los datos desde event.target usando FormData.
// buena práctica: clave única para localStorage
const CONTACT_STORAGE_KEY = 'form';
// 1) render está arriba para poder llamarse desde el submit
function renderSavedMessages() {
const box = document.querySelector('#mensaje-guardado');
const raw = localStorage.getItem(CONTACT_STORAGE_KEY);
if (!box || !raw) return;
const data = JSON.parse(raw);
box.classList.remove('hidden');
box.innerHTML = `
<p><strong>Último mensaje guardado:</strong></p>
<p><strong>Nombre:</strong> ${data.name}</p>
<p><strong>Mensaje:</strong> ${data.message}</p>
`;
}
// 2) manejar el envío del formulario
function handleContactSubmit(event) {
event.preventDefault(); // evita recarga y envío por URL
const form = event.target; // el <form> que disparó el evento
const formData = new FormData(form);
const name = String(formData.get('name'));
const message = String(formData.get('message'));
const payload = {
name,
message,
date: new Date().toISOString(), // timestamp ISO
};
localStorage.setItem(CONTACT_STORAGE_KEY, JSON.stringify(payload));
form.reset();
renderSavedMessages(); // actualiza la UI tras guardar
}
// 3) registrar el listener cuando el formulario exista
const contactForm = document.querySelector('#contact-form');
if (contactForm) {
contactForm.addEventListener('submit', handleContactSubmit);
}
// 4) mostrar datos guardados al cargar la página
renderSavedMessages();
Puntos clave que aparecen y cómo se usan:
- event.preventDefault(): bloquea la recarga y el envío por parámetros en la URL.
- event.target: referencia directa al formulario que emitió el evento.
- FormData API: permite leer valores con formData.get('name').
- Atributo name: debe corresponder con las llaves que lee FormData: 'name' y 'message'.
- Date.toISOString(): genera una marca de tiempo legible y consistente.
- localStorage.setItem + JSON.stringify: guarda un objeto como string.
- form.reset(): limpia los campos después de guardar.
- addEventListener('submit', ...): escucha el submit sin mezclar JS con HTML.
¿Cómo leer localStorage y renderizar el último mensaje guardado?
Para presentar el último mensaje guardado en la interfaz, obtén la cadena desde localStorage, conviértela a objeto con JSON.parse, quita la clase hidden y reemplaza el contenido con innerHTML.
- Usa localStorage.getItem para leer la clave CONTACT_STORAGE_KEY.
- Aplica JSON.parse para volver a objeto.
- Manipula la UI con classList.remove('hidden') e innerHTML usando plantillas.
- Inspecciona en DevTools: pestaña Application, sección Storage, opción Local Storage.
Buenas prácticas que se mencionan y conviene aplicar:
- Define constantes descriptivas para claves: storage key clara y en snake_case o mayúsculas con guiones bajos.
- Separa proyectos en carpetas para mantener el historial y evitar romper avances previos.
- Evita errores por copiar y pegar: verifica IDs, names y rutas.
- Considera validaciones mínimas antes de guardar, por ejemplo: que el mensaje tenga diez caracteres.
- Piensa en escalabilidad: enviar a una API o base de datos cuando sea necesario.
¿Tienes una mejora o un reto resuelto, como validaciones adicionales o un listado histórico de mensajes? Compártelo en los comentarios y cuéntanos tu enfoque para seguir aprendiendo juntos.