Saltar al contenido

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.

  1. Crea o identifica una página .astro que 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>
  2. Añade una etiqueta <form> con algunos inputs a la página. Cada input debería tener un atributo name que 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>
  3. 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,

    • required previene el envío del formulario hasta que el campo esté lleno.
    • minlength establece 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>
  4. El envío del formulario causará que el navegador solicite la página de nuevo. Cambia el method de transferencia de datos del formulario a POST para enviar los datos del formulario como parte del body de la Request, 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>
  5. Verifica el método POST en el frontmatter y accede a los datos del formulario usando Astro.request.formData(). Envuelve esto en un bloque try ... catch para manejar casos cuando la petición POST no fue enviada por un formulario y el formData es inválido.

    src/pages/register.astro
    ---
    export const prerender = false; // Not needed in 'server' mode
    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");
    // 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>
  6. 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 errors y accediéndolo en la plantilla.

    src/pages/register.astro
    ---
    export const prerender = false; // Not needed in 'server' mode
    import { 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>
Contribuir Comunidad Patrocinar