Envio de formulários HTML

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.

Preet SutharFundador, Ikiform

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:

contact.html
<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">
actionResolve paraNum host estático
https://ikiform.com/f/frm_...Exatamente essa URLFunciona. O Ikiform aceita o POST
/api/contacthttps://example.com/api/contactSó funciona se o seu host roda uma função nesse caminho
sendhttps://example.com/company/send, relativo à pasta405 ou 404
"" (empty)A própria página, contact.html405 na maioria dos hosts estáticos
AusenteA própria página405 na maioria dos hosts estáticos
Como o navegador transforma o atributo action de um formulário na URL para onde enviaabsolutorelativo, vazio ou ausenteaction="https://ikiform.com/f/..."usado como escritoIkiform responde303action="send" ounenhumresolvido a partirda páginaou um <base href>, se apágina tiverseu host estáticonão aceita POST: 405Como o navegador transforma o atributo action de um formulário na URL para onde enviaabsolutorelativo, vazio ou ausenteaction="https://ikiform.com/f/..."usado como escritoIkiform responde 303action="send" ou nenhumresolvido a partir dapáginaou um <base href>, se a páginativerseu host estáticonão aceita POST: 405
  1. Um action absoluto é usado exatamente como escrito, então o envio chega ao Ikiform, que responde com um redirecionamento.
  2. 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.
  3. 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.
Se a barra de endereço mostra o seu próprio domínio logo depois de enviar, o action era relativo.
Um elemento <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:

Console
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:

contact.html
<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, formnovalidate e formtarget. Um botão Save draft (salvar rascunho) com formnovalidate pula as checagens do navegador.
  • formaction só 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:

search.html
<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:

footer.html
<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

  1. Em Allowed domains do formulário, adicione o domínio do seu site, mais localhost enquanto desenvolve. Deixe vazio para aceitar envios de qualquer lugar.
  2. Abra a página publicada, não o seu código-fonte, e rode document.querySelector("form").action no console. Ele imprime a URL completa do seu Ikiform.
  3. Envie o formulário. O painel Network mostra um POST para ikiform.com respondido com 303, não um POST para o seu próprio domínio.
  4. 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.
  5. 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

ProblemaCausa e solução
405 Method Not Allowed vindo do seu próprio domínioO 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.comO 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 actionAlguns 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 é seguroO 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 enviadosFormulá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

Travou em algum passo ou quer um guia para o seu caso? Envie um e-mail para hello@ikiform.com.