Construye formularios con rutas API
Un formulario HTML hace que el navegador se actualice o navegue a una nueva página. Para enviar datos de formulario a un endpoint de API en su lugar, debes interceptar el envío del formulario usando JavaScript.
Esta receta muestra como enviar datos de un formulario a un endpoint de API y manejar esos datos.
Prerrequisitos
- Un proyecto con SSR (
output: 'server'
) habilitado - Una integración de Framework UI instalada
Receta
-
Crea un componente de formulario usando tu framework UI. Cada entrada debe tener un atributo
name
que describa el valor de esa entrada.Asegúrate de incluir un elemento
<button>
o<input type="submit">
para enviar el formulario.src/components/FeedbackForm.tsx export default function Form() {return (<form><label>Nombre<input type="text" id="name" name="name" required /></label><label>Correo electrónico<input type="email" id="email" name="email" required /></label><label>Mensaje<textarea id="message" name="message" required /></label><button>Enviar</button></form>);}src/components/FeedbackForm.tsx export default function Form() {return (<form><label>Nombre<input type="text" id="name" name="name" required /></label><label>Correo electrónico<input type="email" id="email" name="email" required /></label><label>Mensaje<textarea id="message" name="message" required /></label><button>Enviar</button></form>);}src/components/FeedbackForm.tsx export default function Form() {return (<form><label>Nombre<input type="text" id="name" name="name" required /></label><label>Correo electrónico<input type="email" id="email" name="email" required /></label><label>Mensaje<textarea id="message" name="message" required /></label><button>Enviar</button></form>);}src/components/FeedbackForm.svelte <form><label>Nombre<input type="text" id="name" name="name" required /></label><label>Correo electrónico<input type="email" id="email" name="email" required /></label><label>Mensaje<textarea id="message" name="message" required /></label><button>Enviar</button></form>src/components/FeedbackForm.vue <template><form><label>Nombre<input type="text" id="name" name="name" required /></label><label>Correo electrónico<input type="email" id="email" name="email" required /></label><label>Mensaje<textarea id="message" name="message" required /></label><button>Enviar</button></form></template> -
Crea el endpoint de API
POST
que recibirá los datos del formulario. Usarequest.formData()
para procesarlos. Asegúrate de validar los valores del formulario antes de usarlos.Este ejemplo manda un objeto JSON con un mensaje de vuelta al cliente.
src/pages/api/feedback.ts import type { APIRoute } from "astro";export const POST: APIRoute = async ({ request }) => {const data = await request.formData();const name = data.get("name");const email = data.get("email");const message = data.get("message");// Valida los datos - probablemente querrás hacer más que estoif (!name || !email || !message) {return new Response(JSON.stringify({message: "Faltan campos requeridos",}),{ status: 400 });}// Haz algo con los datos, luego devuelve una respuesta de éxitoreturn new Response(JSON.stringify({message: "¡Éxito!"}),{ status: 200 });}; -
Crea una función que acepte un evento de envío, luego pásalo como un manejador de eventos
submit
a tu formulario. En la función, llama apreventDefault
en el evento para anular el proceso de envío predeterminado del navegador.Luego, crea un objeto
FormData
y envíalo a tu endpoint usandofetch
.src/components/FeedbackForm.tsx import { useState } from "preact/hooks";export default function Form() {const [responseMessage, setResponseMessage] = useState("");async function submit(e: SubmitEvent) {e.preventDefault();const formData = new FormData(e.target as HTMLFormElement);const response = await fetch("/api/feedback", {method: "POST",body: formData,});const data = await response.json();if (data.message) {setResponseMessage(data.message);}}return (<form onSubmit={submit}><label>Nombre<input type="text" id="name" name="name" required /></label><label>Correo electrónico<input type="email" id="email" name="email" required /></label><label>Mensaje<textarea id="message" name="message" required /></label><button>Enviar</button>{responseMessage && <p>{responseMessage}</p>}</form>);}src/components/FeedbackForm.tsx import { FormEvent, useState } from "react";export default function Form() {const [responseMessage, setResponseMessage] = useState("");async function submit(e: FormEvent<HTMLFormElement>) {e.preventDefault();const formData = new FormData(e.target as HTMLFormElement);const response = await fetch("/api/feedback", {method: "POST",body: formData,});const data = await response.json();if (data.message) {setResponseMessage(data.message);}}return (<form onSubmit={submit}><label htmlFor="name">Nombre<input type="text" id="name" name="name" required /></label><label htmlFor="email">Correo electrónico<input type="email" id="email" name="email" required /></label><label htmlFor="message">Mensaje<textarea id="message" name="message" required /></label><button>Enviar</button>{responseMessage && <p>{responseMessage}</p>}</form>);}src/components/FeedbackForm.tsx import { createSignal, createResource, Suspense } from "solid-js";async function postFormData(formData: FormData) {const response = await fetch("/api/feedback", {method: "POST",body: formData,});const data = await response.json();return data;}export default function Form() {const [formData, setFormData] = createSignal<FormData>();const [response] = createResource(formData, postFormData);function submit(e: SubmitEvent) {e.preventDefault();setFormData(new FormData(e.target as HTMLFormElement));}return (<form onSubmit={submit}><label>Nombre<input type="text" id="name" name="name" required /></label><label>Correo electrónico<input type="email" id="email" name="email" required /></label><label>Mensaje<textarea id="message" name="message" required /></label><button>Enviar</button><Suspense>{response() && <p>{response().message}</p>}</Suspense></form>);}src/components/FeedbackForm.svelte <script lang="ts">let responseMessage: string;async function submit(e: SubmitEvent) {e.preventDefault();const formData = new FormData(e.currentTarget as HTMLFormElement);const response = await fetch("/api/feedback", {method: "POST",body: formData,});const data = await response.json();responseMessage = data.message;}</script><form on:submit={submit}><label>Nombre<input type="text" id="name" name="name" required /></label><label>Correo electrónico<input type="email" id="email" name="email" required /></label><label>Mensaje<textarea id="message" name="message" required /></label><button>Enviar</button>{#if responseMessage}<p>{responseMessage}</p>{/if}</form>src/components/FeedbackForm.vue <script setup lang="ts">import { ref } from "vue";const responseMessage = ref<string>();async function submit(e: Event) {e.preventDefault();const formData = new FormData(e.currentTarget as HTMLFormElement);const response = await fetch("/api/feedback", {method: "POST",body: formData,});const data = await response.json();responseMessage.value = data.message;}</script><template><form @submit="submit"><label>Nombre<input type="text" id="name" name="name" required /></label><label>Correo electrónico<input type="email" id="email" name="email" required /></label><label>Mensaje<textarea id="message" name="message" required /></label><button>Enviar</button><p v-if="responseMessage">{{ responseMessage }}</p></form></template>