Envio de formulários HTML6 min de leitura
O atributo action do formulário HTML, explicado
O que o atributo action de um formulário faz, como valores relativos e vazios são resolvidos, como formaction manda um formulário a dois lugares e por que hosts estáticos respondem 405.
O atributo action é a URL para onde um formulário envia os dados. Um valor relativo é resolvido a partir do endereço da página, um valor vazio ou ausente significa a própria página, e o formaction de um botão de envio o sobrescreve para aquele botão. Num site estático, defina-o como a URL completa de um backend de formulários, como https://ikiform.com/f/<formId>, porque o seu próprio host não aceita o POST.
A maioria dos formulários quebrados em sites estáticos está quebrada neste único atributo. O markup parece certo, o botão funciona, e o navegador mostra um 405 ou uma página em branco, porque os dados foram para um lugar que não consegue recebê-los. Esta página mostra exatamente para onde um dado action manda os dados, e depois usa formaction para direcionar um formulário a duas caixas de entrada.
O que muda aqui
action é uma URL como qualquer href, com uma diferença: um formulário sem action não deixa de fazer algo, ele envia para a página em que está. Num site renderizado no servidor, essa página pode tratar o envio. Num host estático, não pode, então um action ausente ou relativo só falha depois do deploy.
Para onde cada valor manda os dados
Pegue uma página em https://example.com/company/contact.html e cinco formulários nela:
<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 | Resolve para | Num host estático |
|---|---|---|
https://ikiform.com/f/frm_... | Exatamente essa URL | Funciona. O Ikiform aceita o POST |
/api/contact | https://example.com/api/contact | Só funciona se o seu host roda uma função nesse caminho |
send | https://example.com/company/send, relativo à pasta | 405 ou 404 |
"" (empty) | A própria página, contact.html | 405 na maioria dos hosts estáticos |
| Ausente | A própria página | 405 na maioria dos hosts estáticos |
- Um action absoluto é usado exatamente como escrito, então o envio chega ao Ikiform, que responde com um redirecionamento.
- Um action relativo, vazio ou ausente é resolvido a partir do endereço da própria página, ou de um elemento base, se a página tiver um.
- O envio então vai para o seu próprio host. Um host estático só serve arquivos, então recusa o POST, geralmente com 405.
<base href> no head da página muda como toda URL relativa é resolvida, inclusive o action. Alguns criadores de sites e configurações de single-page app adicionam um. Use uma URL completa e isso deixa de importar.Confira o que o navegador vai usar
No console do navegador, o atributo e a propriedade são diferentes. getAttribute devolve o que você escreveu; a propriedade action devolve a URL resolvida para onde o navegador vai realmente enviar:
const form = document.querySelector("form");
form.getAttribute("action");
form.action;Se form.action mostra o seu próprio domínio, é para lá que os dados vão. Criadores como Webflow e Framer costumam definir o action pelo próprio painel de configurações, então confira a página publicada, não o seu código-fonte. Os guias de criadores de sites dizem onde cada criador guarda isso.
Um formulário, duas caixas de entrada
O formaction de um botão de envio substitui o action do formulário só para aquele botão. Aqui, um único conjunto de campos vai para dois formulários do Ikiform. Ask support (falar com o suporte) envia ao formulário de suporte, Talk to sales (falar com vendas) ao formulário de vendas, e cada formulário do Ikiform avisa por e-mail os seus próprios destinatários:
<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 formulário do Ikiform tem seus próprios destinatários de notificação, configurações de spam e webhooks, então suporte e vendas nunca veem os e-mails um do outro.
- Os dois formulários precisam da mesma definição de campos, ou de nenhuma. Com campos definidos, um campo que um formulário não conhece é recusado com
422. - Os outros atributos
form*funcionam do mesmo jeito:formmethod,formenctype,formnovalidateeformtarget. Um botão Save draft (salvar rascunho) comformnovalidatepula as checagens do navegador. formactionsó funciona em botões de envio:<button>,<input type="submit">e<input type="image">.
A alternativa é um único formulário do Ikiform com um campo topic, roteando por assunto num webhook ou nos filtros da sua caixa de entrada. Isso mantém uma lista e uma exportação. Dois formulários são mais simples quando as duas equipes não devem compartilhar destinatários de jeito nenhum.
action com query string
Com method="get", o navegador substitui a query string do action pelos campos do formulário. O lang=de no primeiro formulário abaixo é descartado em silêncio; o segundo o mantém 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>Com method="post" a query string é mantida, porque os campos vão no corpo. Isso não muda nada para o Ikiform: parâmetros de query na URL do endpoint não são armazenados, então use inputs ocultos para valores que você quer guardar.
Inputs fora do formulário
Às vezes o layout precisa de um input que não fica dentro do elemento <form>, como uma inscrição no rodapé ao lado de outro conteúdo. O atributo form num input ou botão o liga a um formulário pelo id, e ele envia para o action desse formulário:
<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: e javascript:
action="mailto:you@example.com" pede ao app de e-mail do visitante para abrir uma mensagem com os campos. Nada é enviado a menos que ele tenha um app de e-mail configurado e aperte enviar, e você nunca fica sabendo que ele tentou. action="javascript:..." roda código em vez de enviar e é bloqueado pela maioria das content security policies. Vale substituir os dois por um endpoint de verdade.
Confira se funciona
- Em Allowed domains do formulário, adicione o domínio do seu site, mais
localhostenquanto desenvolve. Deixe vazio para aceitar envios de qualquer lugar. - Abra a página publicada, não o seu código-fonte, e rode
document.querySelector("form").actionno console. Ele imprime a URL completa do seu Ikiform. - Envie o formulário. O painel Network mostra um POST para
ikiform.comrespondido com303, não um POST para o seu próprio domínio. - No formulário com duas caixas de entrada, envie uma vez com cada botão. Cada envio aparece no seu próprio formulário no painel.
- Confira a caixa de entrada de cada destinatário das notificações. Cada um recebe um e-mail com os campos, e Reply vai para quem enviou quando o formulário tem um campo
email.
Pegadinhas
| Problema | Causa e solução |
|---|---|
405 Method Not Allowed vindo do seu próprio domínio | O action é relativo, vazio ou ausente, então o envio foi para o seu host estático. Use a URL completa do Ikiform |
404 not_found vindo de ikiform.com | O id do formulário no action está errado, ou o formulário foi excluído. Copie o endpoint da página do formulário no painel |
| O criador de sites fica redefinindo o action | Alguns criadores controlam o action do bloco de formulário deles. Use a configuração de action personalizado deles, ou um embed com o seu próprio markup |
| O navegador avisa que o formulário não é seguro | O action usa http: numa página https:. O endpoint do Ikiform é só https:; corrija o esquema |
| Campos de um segundo formulário também são enviados | Formulários não podem ser aninhados. O navegador fecha o formulário externo na tag <form> interna. Use o atributo form em vez disso |
Para o fluxo completo de envio, do clique ao redirecionamento, veja a visão geral. Tudo o que o endpoint aceita está em Formulários HTML.
Perguntas
Ele envia para a página em que está. Isso funciona quando o seu servidor trata envios nessa URL, mas num host estático falha, geralmente com 405 Method Not Allowed.
action é definido no formulário e vale para todo envio. formaction é definido num botão de envio e sobrescreve o action quando aquele botão é usado, então um formulário pode enviar para dois lugares.
Sim. Os navegadores enviam cross-site sem nenhuma configuração especial, e é assim que uma página estática envia a um backend de formulários. O servidor que recebe decide se aceita; o Ikiform confere a origem da página com os domínios permitidos do formulário.
Com method get, o navegador substitui a query string do action pelos campos do próprio formulário. Mova cada parâmetro para um input oculto. Com method post a query string é mantida.
Travou em algum passo ou quer um guia para o seu caso? Envie um e-mail para hello@ikiform.com.