Construir formularios HTML en páginas de Astro
Las páginas de Astro que se renderizan on demand pueden tanto mostrar como manejar formularios. En esta receta, usarás un formulario HTML estándar para enviar datos al servidor. Tu script de frontmatter manejará los datos en el servidor, sin enviar JavaScript al cliente.
En v4.15, Astro añadió actions que proporcionan varios beneficios sobre los formularios HTML básicos, incluyendo validar los datos de tu formulario y actualizar tu UI basándose en el envío del formulario. Para usar este método para construir formularios en su lugar, consulta nuestra guía de actions para aprender más sobre estas funcionalidades.
Requisitos previos
Sección titulada “Requisitos previos”- Un proyecto de Astro con un server adapter instalado.
-
Crea o identifica una página
.astroque contendrá tu formulario y tu código de manejo. Por ejemplo, podrías añadir una página de registro:src/pages/register.astro ------<h1>Register</h1> -
Añade una etiqueta
<form>con algunos inputs a la página. Cada input debería tener un atributonameque describa el valor de ese input.Asegúrate de incluir un elemento
<button>o<input type="submit">para enviar el formulario.src/pages/register.astro ------<h1>Register</h1><form><label>Username:<input type="text" name="username" /></label><label>Email:<input type="email" name="email" /></label><label>Password:<input type="password" name="password" /></label><button>Submit</button></form> -
Usa atributos de validación para proporcionar validación básica del lado del cliente que funciona incluso si JavaScript está deshabilitado.
En este ejemplo,
requiredpreviene el envío del formulario hasta que el campo esté lleno.minlengthestablece una longitud mínima requerida para el texto del input.type="email"también introduce validación que solo aceptará un formato de email válido.
src/pages/register.astro ------<h1>Register</h1><form><label>Username:<input type="text" name="username" required /></label><label>Email:<input type="email" name="email" required /></label><label>Password:<input type="password" name="password" required minlength="6" /></label><button>Submit</button></form>Puedes añadir lógica de validación personalizada que se refiera a múltiples campos usando una etiqueta
<script>y la Constraint Validation API.Para escribir lógica de validación compleja más fácilmente, puedes construir tu formulario usando un framework de frontend y elegir una librería de formularios como React Hook Form o Felte.
-
El envío del formulario causará que el navegador solicite la página de nuevo. Cambia el
methodde transferencia de datos del formulario aPOSTpara enviar los datos del formulario como parte del body de laRequest, en lugar de como parámetros de URL.src/pages/register.astro ------<h1>Register</h1><form method="POST"><label>Username:<input type="text" name="username" required /></label><label>Email:<input type="email" name="email" required /></label><label>Password:<input type="password" name="password" required minlength="6" /></label><button>Submit</button></form> -
Verifica el método
POSTen el frontmatter y accede a los datos del formulario usandoAstro.request.formData(). Envuelve esto en un bloquetry ... catchpara manejar casos cuando la peticiónPOSTno fue enviada por un formulario y elformDataes inválido.src/pages/register.astro ---export const prerender = false; // Not needed in 'server' modeif (Astro.request.method === "POST") {try {const data = await Astro.request.formData();const name = data.get("username");const email = data.get("email");const password = data.get("password");// Do something with the data} catch (error) {if (error instanceof Error) {console.error(error.message);}}}---<h1>Register</h1><form method="POST"><label>Username:<input type="text" name="username" required /></label><label>Email:<input type="email" name="email" required /></label><label>Password:<input type="password" name="password" required minlength="6" /></label><button>Submit</button></form> -
Valida los datos del formulario en el servidor. Esto debería incluir la misma validación hecha en el cliente para prevenir envíos maliciosos a tu endpoint y para soportar el raro navegador antiguo que no tiene validación de formularios.
También puede incluir validación que no se puede hacer en el cliente. Por ejemplo, este ejemplo verifica si el email ya está en la base de datos.
Los mensajes de error pueden enviarse de vuelta al cliente almacenándolos en un objeto
errorsy accediéndolo en la plantilla.src/pages/register.astro ---export const prerender = false; // Not needed in 'server' modeimport { isRegistered, registerUser } from "../../data/users"import { isValidEmail } from "../../utils/isValidEmail";const errors = { username: "", email: "", password: "" };if (Astro.request.method === "POST") {try {const data = await Astro.request.formData();const name = data.get("username");const email = data.get("email");const password = data.get("password");if (typeof name !== "string" || name.length < 1) {errors.username += "Please enter a username. ";}if (typeof email !== "string" || !isValidEmail(email)) {errors.email += "Email is not valid. ";} else if (await isRegistered(email)) {errors.email += "Email is already registered. ";}if (typeof password !== "string" || password.length < 6) {errors.password += "Password must be at least 6 characters. ";}const hasErrors = Object.values(errors).some(msg => msg)if (!hasErrors) {await registerUser({name, email, password});return Astro.redirect("/login");}} catch (error) {if (error instanceof Error) {console.error(error.message);}}}---<h1>Register</h1><form method="POST"><label>Username:<input type="text" name="username" /></label>{errors.username && <p>{errors.username}</p>}<label>Email:<input type="email" name="email" required /></label>{errors.email && <p>{errors.email}</p>}<label>Password:<input type="password" name="password" required minlength="6" /></label>{errors.password && <p>{errors.password}</p>}<button>Register</button></form>