Menu

Formulário HTML: action, method, fieldset e validação

Como montar um formulário em HTML: o elemento form, atributos name, action e method (GET vs POST), agrupar com fieldset e legend, validação nativa com required e pattern, e tratar o envio no JavaScript.

Esta página tem editores executáveis - edite, execute e veja a saída na hora.

Como fazer um formulário em HTML

Um formulário é um elemento <form> com campos e um botão de envio. Cada campo precisa de um name: é a chave com que o valor é enviado. Preencha o formulário e aperte Send. A prévia não envia nada para lugar nenhum; ela mostra exatamente o que o navegador teria enviado.

As partes:

  • action é a URL para onde os dados vão, e method é como (post aqui).
  • name em todo campo. O valor é o que o usuário digitou.
  • <label> dá nome a cada campo na tela e para os leitores de tela (veja label no HTML).
  • required e type="email" fazem o navegador verificar os campos antes de enviar. Tente enviar com o nome vazio, ou com abc no e-mail.
  • O botão de envio envia o formulário. Apertar Enter num campo de texto também envia.

action e method: para onde e como os dados vão

AtributoValoresPadrão
actionQualquer URLA URL da página atual
methodget, post, dialogget
enctypeapplication/x-www-form-urlencoded, multipart/form-data, text/plainapplication/x-www-form-urlencoded

Com method="get", os campos viram a query string da URL: um formulário de busca com name="q" vai para /search?q=blue+shoes. Isso é o certo para buscas e filtros, porque o resultado pode ir para os favoritos e ser compartilhado. Com method="post", os campos vão no corpo da requisição e não aparecem na barra de endereço nem no histórico. Use POST para tudo o que faz login, cria, altera ou apaga algo, e para senhas.

Um formulário com upload de arquivo (<input type="file">) precisa de method="post" e enctype="multipart/form-data", senão só o nome do arquivo é enviado. method="dialog" é para um formulário dentro de um <dialog>: enviar fecha o diálogo em vez de fazer uma requisição.

O que é enviado

Só os campos com name são enviados, e só quando não estão disabled. Aperte Submit e compare os campos com o que o formulário envia:

O formulário envia city, zip, source e action. O campo sem nome, o campo desativado e o checkbox desmarcado ficam de fora. Inputs ocultos são enviados, mas nunca aparecem, e o botão de envio manda o seu próprio name e value porque foi o botão usado.

Agrupando campos com fieldset e legend

<fieldset> desenha uma caixa em volta de campos relacionados, e <legend> é a sua legenda. Os leitores de tela anunciam a legenda quando o foco entra no grupo, e é isso que torna compreensível um conjunto de radio buttons como o de baixo: "Delivery, Standard, botão de opção".

disabled num fieldset desativa todos os campos dentro dele de uma vez, e nenhum deles é enviado. Remova o atributo e os campos de presente passam a funcionar.

Validação nativa: required, pattern e companhia

Os navegadores verificam estes atributos antes de enviar e mostram uma mensagem no primeiro campo que falha:

AtributoVerifica
requiredO campo não está vazio (um checkbox está marcado)
type="email", type="url"O valor parece um endereço de e-mail ou uma URL
minlength, maxlengthTamanho do texto
min, max, stepFaixa de números e datas
patternO valor inteiro corresponde a uma expressão regular

:invalid e :valid estilizam os campos pelo estado. :user-invalid costuma ser melhor: só se aplica depois que o usuário alterou o campo e saiu dele, ou tentou enviar, então um formulário vazio não abre todo em vermelho.

Três coisas sobre pattern confundem muita gente. Ele precisa corresponder ao valor inteiro (não precisa de ^ nem $). Só roda quando o campo não está vazio, então combine com required. E a mensagem de erro do navegador é genérica, então descreva o formato num texto visível ao lado do campo. Chrome e Firefox acrescentam o texto do title à mensagem, mas é fácil não perceber.

Para desligar as verificações, por exemplo enquanto você testa a validação do servidor, adicione novalidate ao <form>. Um único botão de envio pode pulá-las com formnovalidate.

A validação do navegador existe para a comodidade do usuário. Qualquer pessoa pode editar a página ou enviar uma requisição sem ela, então o servidor precisa verificar cada valor de novo.

Mensagens personalizadas com setCustomValidity

Quando uma regra não pode ser escrita como atributo, como "as duas senhas precisam ser iguais", defina a mensagem pelo JavaScript. Um campo com uma mensagem personalizada não vazia é inválido; uma string vazia o torna válido de novo:

O campo de repetição não tem name, então só uma cópia da senha é enviada.

Tratando o envio no JavaScript

Para enviar o formulário sem sair da página, escute submit, chame preventDefault() e leia os campos com FormData. Escutar submit em vez do click de um botão pega todas as formas de envio, inclusive Enter, e só roda depois que a validação nativa passou:

Object.fromEntries(new FormData(form)) transforma os campos num objeto simples. Para campos que podem ter vários valores (checkboxes com o mesmo nome, um select múltiplo), use formData.getAll('name'), porque o objeto guarda só o último valor.

Erros comuns

  • Campos sem name. Eles ficam de fora dos dados enviados sem nenhum aviso.
  • Placeholders no lugar de labels. A dica some assim que o usuário digita. Use um <label>.
  • Um <button> sem type usado para algo que não é enviar. Dentro de um formulário ele é um botão de envio.
  • Um formulário dentro de outro. Aninhar formulários é inválido; o navegador ignora a tag <form> interna.
  • Escutar click no botão de envio em vez de submit no formulário. Os envios pela tecla Enter se perdem.
  • Confiar na validação do navegador do lado do servidor. Valide de novo lá.
  • GET para senhas. Elas vão parar na URL, no histórico e nos logs do servidor.

Perguntas frequentes

Como criar um formulário no HTML?

Envolva os campos em <form action="/signup" method="post">, dê a cada campo um name e um <label> e termine com <button type="submit">. Quando o formulário é enviado, o navegador manda cada par name=value para a URL do action.

Qual a diferença entre GET e POST num formulário?

method="get" (o padrão) coloca os campos na URL, como em /search?q=shoes, o que serve para buscas e filtros que devem poder ir para os favoritos. method="post" os envia no corpo da requisição, que é o que você quer para login, cadastro e tudo o que altera dados.

Por que um campo do meu formulário não está sendo enviado?

Ele não tem atributo name, ou está disabled. Só campos com nome e ativos são enviados. Um checkbox ou radio button desmarcado também fica totalmente de fora.

Para que servem fieldset e legend?

<fieldset> agrupa campos relacionados e <legend> é a legenda do grupo. Os leitores de tela anunciam a legenda quando o foco entra no grupo, e é isso que torna um grupo de radio buttons compreensível; disabled num fieldset desativa todos os campos dentro dele.

Como validar um formulário em HTML sem JavaScript?

Use atributos: required, type="email", minlength, maxlength, min, max e pattern. O navegador bloqueia o envio e mostra uma mensagem no primeiro campo inválido. Valide sempre no servidor também, porque essas verificações rodam no navegador do usuário e podem ser contornadas.

Como impedir que o formulário recarregue a página?

Escute o evento submit do formulário e chame event.preventDefault(), depois envie os dados você mesmo com fetch: form.addEventListener('submit', (e) => { e.preventDefault(); fetch(form.action, { method: 'POST', body: new FormData(form) }); }).

Coddy programming languages illustration

Aprenda a programar com o Coddy

COMEÇAR