Envío de formularios HTML6 min de lectura
El atributo action de un formulario HTML, explicado
Qué hace el atributo action de un formulario, cómo se resuelven los valores relativos y vacíos, cómo formaction envía un formulario a dos sitios y por qué los hostings estáticos responden 405.
El atributo action es la URL a la que un formulario envía sus datos. Un valor relativo se resuelve respecto a la dirección de la página, uno vacío o ausente significa la propia página, y el formaction de un botón de envío lo sobrescribe para ese botón. En un sitio estático, ponle la URL completa de un backend de formularios como https://ikiform.com/f/<formId>, porque tu propio hosting no puede aceptar el POST.
La mayoría de formularios rotos en sitios estáticos fallan en este único atributo. El markup parece correcto, el botón funciona y el navegador muestra un 405 o una página en blanco, porque los datos fueron a un sitio que no puede recibirlos. Esta página muestra exactamente adónde envía los datos un action concreto, y luego usa formaction para dirigir un formulario a dos bandejas de entrada.
Qué cambia aquí
action es una URL como cualquier href, con un matiz: un formulario sin action no deja de hacer nada, envía a la página en la que está. En un sitio renderizado en el servidor, esa página podría gestionar el envío. En un hosting estático no puede, así que un action ausente o relativo solo falla después de desplegar.
Adónde envía los datos cada valor
Toma una página en https://example.com/company/contact.html con cinco formularios:
<form action="https://ikiform.com/f/frm_xxxxxxxxxxxxxxxx" method="post">
<form action="/api/contact" method="post">
<form action="send" method="post">
<form action="" method="post">
<form method="post">| action | Se resuelve como | En un hosting estático |
|---|---|---|
https://ikiform.com/f/frm_... | Exactamente esa URL | Funciona. Ikiform acepta el POST |
/api/contact | https://example.com/api/contact | Solo funciona si tu hosting ejecuta una función en esa ruta |
send | https://example.com/company/send, relativa a la carpeta | 405 o 404 |
"" (empty) | La propia página, contact.html | 405 en la mayoría de hostings estáticos |
| Ausente | La propia página | 405 en la mayoría de hostings estáticos |
- Un action absoluto se usa exactamente como está escrito, así que el envío llega a Ikiform, que responde con una redirección.
- Un action relativo, vacío o ausente se resuelve respecto a la dirección de la propia página, o respecto a un elemento base si la página tiene uno.
- El envío va entonces a tu propio hosting. Un hosting estático solo sirve archivos, así que rechaza el POST, normalmente con 405.
<base href> en el head de la página cambia cómo se resuelve cada URL relativa, incluido action. Algunos creadores de sitios y configuraciones de apps de una sola página añaden uno. Usa una URL completa y no importará.Comprueba qué usará el navegador
En la consola del navegador, el atributo y la propiedad son distintos. getAttribute devuelve lo que escribiste; la propiedad action devuelve la URL resuelta a la que el navegador enviará de verdad:
const form = document.querySelector("form");
form.getAttribute("action");
form.action;Si form.action muestra tu propio dominio, ahí es adonde van los datos. Creadores como Webflow y Framer suelen poner el action desde su propio panel de ajustes, así que revisa la página publicada, no tu código fuente. Las guías de creadores de sitios indican dónde lo guarda cada creador.
Un formulario, dos bandejas de entrada
El formaction de un botón de envío sustituye el action del formulario solo para ese botón. Aquí, un mismo conjunto de campos va a dos formularios de Ikiform. Ask support envía al formulario de soporte, Talk to sales al de ventas, y cada formulario de Ikiform manda email a sus propios destinatarios:
<form action="https://ikiform.com/f/frm_supportxxxxxxxxx" method="post">
<label for="email">Email</label>
<input id="email" name="email" type="email" autocomplete="email" required />
<label for="message">How can we help?</label>
<textarea id="message" name="message" rows="5" required></textarea>
<input name="_gotcha" type="text" tabindex="-1" autocomplete="off" hidden />
<button>Ask support</button>
<button formaction="https://ikiform.com/f/frm_salesxxxxxxxxxxx">Talk to sales</button>
</form>- Cada formulario de Ikiform tiene sus propios destinatarios de notificaciones, ajustes de spam y webhooks, así que soporte y ventas nunca ven el correo del otro.
- Los dos formularios necesitan la misma definición de campos, o ninguna. Con campos definidos, un campo que un formulario no conoce se rechaza con
422. - Los demás atributos
form*funcionan igual:formmethod,formenctype,formnovalidateyformtarget. Un botón Save draft conformnovalidatese salta las comprobaciones del navegador. formactionsolo funciona en botones de envío:<button>,<input type="submit">e<input type="image">.
La alternativa es un único formulario de Ikiform con un campo topic, y enrutar por tema en un webhook o con los filtros de tu bandeja de entrada. Así mantienes una sola lista y una sola exportación. Dos formularios son más sencillos cuando los dos equipos no deberían compartir destinatarios en absoluto.
action con query string
Con method="get", el navegador sustituye la query string del action por los campos del formulario. El lang=de del primer formulario de abajo se descarta sin avisar; el segundo lo conserva como input oculto:
<form action="/search?lang=de" method="get">
<input name="q" />
</form>
<form action="/search" method="get">
<input name="q" />
<input type="hidden" name="lang" value="de" />
</form>Con method="post" la query string se conserva, porque los campos van en el cuerpo. Eso no cambia nada para Ikiform: los parámetros de query de la URL del endpoint no se guardan, así que usa inputs ocultos para los valores que quieras conservar.
Inputs fuera del formulario
A veces el diseño necesita un input que no está dentro del elemento <form>, como un registro en el pie junto a otro contenido. El atributo form en un input o un botón lo une a un formulario por id, y envía al action de ese formulario:
<form id="newsletter" action="https://ikiform.com/f/frm_xxxxxxxxxxxxxxxx" method="post"></form>
<footer>
<input form="newsletter" name="email" type="email" required />
<button form="newsletter">Subscribe</button>
</footer>Actions mailto: y javascript:
action="mailto:you@example.com" pide a la app de correo del visitante que abra un mensaje con los campos. No se envía nada salvo que tenga una app de correo configurada y pulse enviar, y nunca sabrás que lo intentó. action="javascript:..." ejecuta código en lugar de enviar y lo bloquean la mayoría de políticas de seguridad de contenido. Merece la pena sustituir ambos por un endpoint real.
Comprueba que funciona
- En Allowed domains del formulario, añade el dominio de tu sitio, y
localhostmientras desarrollas. Déjalo vacío para aceptar envíos desde cualquier lugar. - Abre la página publicada, no tu código fuente, y ejecuta
document.querySelector("form").actionen la consola. Imprime tu URL completa de Ikiform. - Envía el formulario. El panel Network muestra un POST a
ikiform.comrespondido con303, no un POST a tu propio dominio. - En el formulario de dos bandejas, envía una vez con cada botón. Cada envío aparece bajo su propio formulario en el panel.
- Revisa la bandeja de entrada de cada destinatario de las notificaciones. Cada uno recibe un email con los campos, y Reply va a quien envió el formulario cuando este tiene un campo
email.
Errores comunes
| Problema | Causa y solución |
|---|---|
405 Method Not Allowed desde tu propio dominio | El action es relativo, está vacío o falta, así que el envío fue a tu hosting estático. Usa la URL completa de Ikiform |
404 not_found desde ikiform.com | El id del formulario en el action es incorrecto, o el formulario se eliminó. Copia el endpoint desde la página del formulario en el panel |
| El creador sigue restableciendo el action | Algunos creadores controlan el action de su bloque de formulario. Usa su ajuste de action personalizado, o un embed con tu propio markup |
| El navegador avisa de que el formulario no es seguro | El action usa http: en una página https:. El endpoint de Ikiform es solo https:; corrige el esquema |
| También se envían campos de un segundo formulario | Los formularios no se pueden anidar. El navegador cierra el formulario exterior en la etiqueta <form> interior. Usa el atributo form en su lugar |
Para el flujo completo de un envío, del clic a la redirección, consulta el resumen. Todo lo que acepta el endpoint está en Formularios HTML.
Preguntas
Envía a la página en la que está. Funciona cuando tu servidor gestiona envíos en esa URL, pero en un hosting estático falla, normalmente con 405 Method Not Allowed.
action se pone en el formulario y se aplica a todos los envíos. formaction se pone en un botón de envío y sobrescribe action cuando se usa ese botón, así que un formulario puede enviar a dos sitios.
Sí. Los navegadores envían entre sitios sin ninguna configuración especial, que es como una página estática envía a un backend de formularios. El servidor que recibe decide si lo acepta; Ikiform comprueba el origen de la página con los dominios permitidos del formulario.
Con method get, el navegador sustituye la query string del action por los propios campos del formulario. Pasa cada parámetro a un input oculto. Con method post la query string se conserva.
¿Te atascaste en un paso o quieres una guía para tu caso? Escribe a hello@ikiform.com.