O Guia Completo de Formulários HTML e Validação de Restrições

Neste artigo, examinamos os campos de formulário HTML e as opções de validação oferecidas pelo HTML5. Também veremos como essas opções podem ser aprimoradas através do uso do CSS e JavaScript.

O que é Validação por Restrições?

Cada campo de formulário tem um propósito. E esse propósito é frequentemente governado por restrições — ou as regras que regem o que deve e não deve ser inserido em cada campo de formulário. Por exemplo, um campo email exigirá um endereço de email válido; um campo senha pode exigir certos tipos de caracteres e ter um número mínimo de caracteres necessários; e um campo de texto pode ter um limite no número de caracteres que podem ser inseridos.

Navegadores modernos têm a capacidade de verificar se essas restrições estão sendo observadas pelos usuários e podem alertá-los quando essas regras são violadas. Isso é conhecido como validação por restrições.

Validação no Cliente vs. Validação no Servidor

A maioria do código JavaScript escrito nos primeiros anos da linguagem lidava com a validação de formulários no cliente. Mesmo hoje, os desenvolvedores passam considerável tempo escrevendo funções para verificar os valores dos campos. Isso ainda é necessário em navegadores modernos? Provavelmente não. Na maioria dos casos, realmente depende do que você está tentando fazer.

Mas primeiro, aqui está uma grande mensagem de aviso:

A validação no cliente é uma conveniência que pode impedir erros comuns de entrada de dados antes que um aplicativo perca tempo e largura de banda enviando dados para um servidor. Não é um substituto para a validação no servidor!

Sempre sanitize os dados no lado do servidor. Nem todas as requisições virão de um navegador. Mesmo quando o fazem, não há garantia de que o navegador validou os dados. Qualquer pessoa que saiba como abrir as ferramentas do desenvolvedor do navegador também pode contornar seu cuidadosamente elaborado HTML e JavaScript.

Campos de Entrada HTML5

O HTML oferece:

Mas você usará <input> mais frequentemente:

<input type="text" name="username" />

O atributo type define o tipo de controle, e há uma grande variedade de opções:

type description
button a button with no default behavior
checkbox a check/tick box
color a color picker
date a date picker for the year, month, and day
datetime-local a date and time picker
email an email entry field
file a file picker
hidden a hidden field
image a button which displays the image defined by the src attribute
month a month and year picker
number a number entry field
password a password entry field with obscured text
radio a radio button
range a slider control
reset a button that resets all form inputs to their default values (but avoid using this, as it’s rarely useful)
search a search entry field
submit a form submission button
tel a telephone number entry field
text a text entry field
time a time picker with no time zone
url a URL entry field
week a week number and year picker

O navegador recua para text se você omitir o atributo type ou se não suportar uma opção. Navegadores modernos têm suporte adequado para todos os tipos, mas navegadores antigos ainda exibirão um campo de entrada de texto.

Outros atributos úteis de <input> incluem:

attribute description
accept file upload type
alt alternative text for the image types
autocomplete hint for field auto-completion
autofocus focus field on page load
capture media capture input method
checked checkbox/radio is checked
disabled disable the control (it won’t be validated or have its value submitted)
form associate with a form using this ID
formaction URL for submission on submit and image buttons
inputmode data type hint
list ID of <datalist> autocomplete options
max maximum value
maxlength maximum string length
min minimum value
minlength minimum string length
name name of control, as submitted to server
pattern a regular expression pattern, such as [A-Z]+ for one or more uppercase characters
placeholder placeholder text when the field value is empty
readonly the field is not editable, but it will still be validated and submitted
required the field is required
size the size of the control (often overridden in CSS)
spellcheck set true or false spell-checking
src image URL
step incremental values in numbers and ranges
type field type (see above)
value the initial value

Campos de Saída HTML

Além dos tipos de entrada, o HTML5 fornece saídas somente leitura:

  • output: um resultado de texto de um cálculo ou ação do usuário
  • progress: uma barra de progresso com atributos value e max
  • meter: uma escala que pode mudar entre verde, âmbar e vermelho, dependendo dos valores definidos para os atributos value, min, max, low, high e optimum.

Labels de Entrada

Os campos devem ter um <label> associado, que você pode envolver em torno do elemento:

<label>your name <input type="text" name="name" /><label>

Ou vincule o campo pelo id ao rótulo usando um atributo for:

<label for="nameid">your name</label>
<input type="text" id="nameid" name="name" />

Os rótulos são importantes para acessibilidade. Você pode ter encontrado formulários que usam um placeholder para economizar espaço na tela:

<input type="text" name="name" value="" placeholder="your name" />

O texto do espaço reservado desaparece assim que o usuário digita algo – mesmo um único espaço. É melhor mostrar um rótulo do que forçar o usuário a lembrar o que o campo queria!

Comportamentos de Entrada

Tipos de campo e atributos de restrição alteram o comportamento de entrada do navegador. Por exemplo, uma entrada number mostra um teclado numérico em dispositivos móveis. O campo pode mostrar uma seta e os cliques de teclado para cima/para baixo incrementarão e decrementarão os valores.

A maioria dos tipos de campo é óbvia, mas existem exceções. Por exemplo, cartões de crédito são numéricos, mas o spinner de incremento/decremento é inútil e é muito fácil apertar para cima ou para baixo ao inserir um número de 16 dígitos. É melhor usar um tipo padrão text, mas definir o atributo inputmode como numeric, o que mostra um teclado apropriado. Definir autocomplete="cc-number" também sugere quaisquer cartões de crédito pré-configurados ou digitados anteriormente.

Usar o tipo de campo correto type e autocorrect oferece benefícios que seriam difíceis de alcançar em JavaScript. Por exemplo, alguns navegadores móveis podem:

Validação Automática

O navegador garante que o valor de entrada se adeque às restrições definidas pelos atributos type, min, max, step, minlength, maxlength, pattern e required. Por exemplo:

<input type="number" min="1" max="100" required />

Tentativa de enviar um valor vazio impede a submissão do formulário e mostra a seguinte mensagem no Chrome:

Os seletores não permitirão valores fora do intervalo de 1 a 100. Mensagens de validação semelhantes aparecem se você digitar uma string que não seja um número. Tudo isso sem uma única linha de JavaScript.

Você pode desativar a validação do navegador por:

  • adicionando um atributo novalidate ao elemento <form>
  • adicionando um atributo formnovalidate ao botão de envio ou imagem

Criando Entradas Personalizadas em JavaScript

Se você está escrevendo um novo componente de entrada de data baseado em JavaScript, pare e afaste-se do seu teclado!

Escrever controles de entrada personalizados é difícil. Você precisa considerar o mouse, teclado, toque, fala, acessibilidade, dimensões da tela e o que acontece quando o JavaScript falha. Você também está criando uma experiência de usuário diferente. Talvez seu controle seja superior ao seletor de datas padrão no desktop, iOS e Android, mas a UI desconhecida confundirá alguns usuários.

Há três razões principais pelas quais os desenvolvedores escolhem criar entradas baseadas em JavaScript.

1. Os controles padrão são difíceis de estilizar

O estilo CSS é limitado e geralmente requer hacks, como sobrepor uma entrada com os pseudo-elementos ::before e ::after do rótulo. A situação está melhorando, mas questione qualquer design que priorize a forma sobre a função.

2. Tipos modernos de <input> não são suportados em navegadores antigos

Em essência, você está codificando para o Internet Explorer. Os usuários do IE não terão um seletor de datas, mas ainda podem inserir datas no formato AAAA-MM-DD. Se seu cliente insistir, então carregue um polyfill apenas no IE. Não há necessidade de sobrecarregar navegadores modernos.

3. Você precisa de um novo tipo de entrada que nunca foi implementado antes

Essas situações são raras, mas sempre comece com campos apropriados do HTML5. Eles são rápidos e funcionam mesmo antes do script ser carregado. Você pode aprimorar progressivamente os campos conforme necessário. Por exemplo, uma pitada de JavaScript pode garantir que a data de término de um evento do calendário ocorra após a data de início.

Em resumo: evite reinventar controles HTML!

Estilo de Validação CSS

Você pode aplicar os seguintes pseudo-classes a campos de entrada para estilizá-los de acordo com o estado atual:

selector description
:focus the field with focus
:focus-within an element contains a field with focus (yes, it’s a parent selector!)
:focus-visible an element has focus owing to keyboard navigation, so a focus ring or more evident styling is necessary
:required a field with a required attribute
:optional a field without a required attribute
:valid a field that has passed validation
:invalid a field that has not passed validation
:user-valid a field that has passed validation after the user has interacted with it (Firefox only)
:user-invalid a field that hasn’t passed validation after the user has interacted with it (Firefox only)
:in-range the value is within range on a number or range input
:out-of-range the value is out of range on a number or range input
:disabled a field with a disabled attribute
:enabled a field without a disabled attribute
:read-only a field with a read-only attribute
:read-write: a field without a read-only attribute
:checked a checked checkbox or radio button
:indeterminate an indeterminate checkbox or radio state, such as when all radio buttons are unchecked
:default the default submit button or image

Você pode estilizar o texto do placeholder de uma entrada com o pseudo-elemento ::placeholder:

/* texto de placeholder azul em campos de email */
input[type="email"]::placeholder {
  color: blue;
}

Os seletores acima têm a mesma especificidade, então a ordem pode ser importante. Considere este exemplo:

input:invalid { color: red; }
input:enabled { color: black; }

Entradas inválidas têm texto vermelho, mas isso é aplicado apenas a entradas com um atributo disabledentão todas as entradas habilitadas são pretas.

O navegador aplica estilos de validação na carga da página. Por exemplo, no código a seguir, cada campo inválido é dado um contorno vermelho:

:invalid {
  border-color: #900;
}

O usuário enfrenta um conjunto assustador de caixas vermelhas antes de interagir com o formulário. Mostrar erros de validação após o primeiro envio ou conforme um valor é alterado ofereceria uma melhor experiência. É aí que entra o JavaScript…

JavaScript e a API de Validação de Restrições

A API de Validação de Restrições oferece opções de personalização de formulários que podem melhorar o verificação de campo HTML padrão. Você poderia:

  • impedir a validação até que o usuário interaja com um campo ou envie o formulário
  • mostrar mensagens de erro com estilo personalizado
  • fornecer validação personalizada que é impossível apenas com HTML. Isso geralmente é necessário quando você precisa comparar duas entradas — como ao inserir um endereço de email ou um número de telefone, verificar se os campos “novo” e “confirmar” de senha têm o mesmo valor, ou garantir que uma data venha depois de outra.

Validação de Formulários

Antes de usar a API, seu código deve desabilitar a validação padrão e mensagens de erro definindo a propriedade noValidate do formulário como true (o mesmo que adicionar um atributo novalidate):

const myform = document.getElementById('myform');
myform.noValidate = true;

Você pode então adicionar manipuladores de eventos — como quando o formulário é enviado:

myform.addEventListener('submit', validateForm);

O manipulador pode verificar se todo o formulário é válido usando os métodos checkValidity() ou reportValidity(), que retornam true quando todos os inputs do formulário são válidos. (A diferença é que checkValidity() verifica se algum input está sujeito à validação de restrições.)

Os documentos da Mozilla explicam:

Um evento inválido também é acionado em cada campo inválido. Isso não se propaga: os manipuladores devem ser adicionados a cada controle que o utiliza.

// validar formulário na submissão
function validateForm(e) {

  const form = e.target;

  if (form.checkValidity()) {

    // formulário é válido - fazer verificações adicionais

  }
  else {

    // formulário é inválido - cancelar envio
    e.preventDefault();

  }

};

A valid form could now incur further validation checks. Similarly, an invalid form could have invalid fields highlighted.

Validação de Campo

Campos individuais têm as seguintes propriedades de validação de restrição:

  • willValidate: retorna true se o elemento for um candidato para validação de restrição.

  • validationMessage: a mensagem de validação. Isso será uma string vazia se o campo for válido.

  • valitity: um objeto ValidityState. Isso possui uma propriedade válida definida como verdadeira quando o campo é válido. Se for falso, uma ou mais das seguintes propriedades serão verdadeiras:

    ValidityState descrição
    .badInput o navegador não consegue entender a entrada
    .customError uma mensagem de validade personalizada foi definida
    .patternMismatch o valor não corresponde ao atributo padrão especificado
    .rangeOverflow o valor é maior que o atributo máximo
    .rangeUnderflow o valor é menor que o atributo mínimo
    .stepMismatch o valor não se encaixa nas regras do atributo passo
    .tooLong o comprimento da string é maior que o atributo maxlength
    .tooShort o comprimento da string é menor que o atributo minlength
    .typeMismatch o valor não é um email ou URL válido
    .valueMissing um valor obrigatório está vazio

Os campos individuais possuem os seguintes métodos de validação de restrição:

  • setCustomValidity(message): define uma mensagem de erro para um campo inválido. Deve ser passado uma string vazia quando o campo é válido, caso contrário, o campo permanecerá inválido para sempre.
  • checkValidity(): retorna true quando a entrada é válida. A propriedade valitity.valid faz a mesma coisa, mas checkValidity() também dispara um evento invalid no campo, o que pode ser útil.

A função manipuladora validateForm() pode percorrer todos os campos e aplicar uma classe invalid ao elemento pai quando necessário:

function validateForm(e) {
  const form = e.target;
  if (form.checkValidity()) {
    // o formulário é válido - faça verificações adicionais
  }
  else {
    // o formulário é inválido - cancelar envio
    e.preventDefault();
    // aplicar classe inválida
    Array.from(form.elements).forEach(i => {
      if (i.checkValidity()) {
        // campo é válido - remover classe
        i.parentElement.classList.remove('invalid');
      }
      else {
        // campo é inválido - adicionar classe
        i.parentElement.classList.add('invalid');
      }
    });
  }
};

Suponha que seu HTML definiu um campo de email:

<div>
  <label for="email">email</label>
  <input type="email" id="email" name="email" required />
  <p class="help">Please enter a valid email address</p>
</div>

O script aplica uma classe invalid ao <div> quando o email não é especificado ou é inválido. O CSS pode mostrar ou ocultar a mensagem de validação quando o formulário é enviado:

.help { display: none; }
.invalid .help { display: block; }
.invalid label, .invalid input, .invalid .help {
  color: red;
  border-color: red;
}

Criando um Validador de Formulários Personalizado

A seguinte demonstração mostra um exemplo de formulário de contato que requer um nome de usuário e uma das opções: um endereço de email, um número de telefone, ou ambos:

Ele é implementado usando uma classe de validação de formulários genérica chamada FormValidate. Um elemento de formulário é passado ao instanciar um objeto. Um segundo parâmetro opcional pode ser definido:

  • true para validar cada campo à medida que o usuário interage com ele
  • false (o padrão) para validar todos os campos após o primeiro envio (a validação de campo ocorre após isso)
// validar formulário de contato
const contactForm = new FormValidate(document.getElementById('contact'), false);

Um método .addCustom(field, func) define funções de validação personalizadas. O código a seguir garante que os campos email ou tel sejam válidos (nenhum deles tem atributos required):

// validação personalizada - email e/ou telefone
const
  email = document.getElementById('email'),
  tel = document.getElementById('tel');

contactForm.addCustom(email, f => f.value || tel.value);
contactForm.addCustom(tel, f => f.value || email.value);

A FormValidate object monitors both of the following:

  • focusout eventos, que então verificam um campo individual
  • eventos submit do formulário, que então verificam todos os campos

Ambos chamam o método .validateField(field), que verifica se um campo passa pela validação de restrição padrão. Quando isso acontece, qualquer função de validação personalizada atribuída a esse campo executa em seguida. Todas devem retornar true para que o campo seja válido.

Campos inválidos têm uma classe invalid aplicada ao elemento pai do campo, que exibe uma mensagem de ajuda vermelha usando CSS.

Por fim, o objeto chama uma função personalizada submit quando todo o formulário é válido:

// submit personalizado
contactForm.submit = e => {
  e.preventDefault();
  alert('Form is valid!\n(open the console)');
  const fd = new FormData(e.target);
  for (const [name, value] of fd.entries()) {
    console.log(name + ': ' + value);
  }
}

Alternativamente, você pode usar um addEventListener padrão para lidar com eventos submit do formulário, uma vez que FormValidate impede que outros manipuladores sejam executados quando o formulário é inválido.

Form Finesse

Formulários são a base de todos os aplicativos web e os desenvolvedores gastam considerável tempo manipulando a entrada do usuário. A validação de restrições é bem suportada: os navegadores podem lidar com a maioria dos testes e mostrar opções de entrada apropriadas.

Recomendações:

  • Use os tipos de entrada HTML padrão sempre que possível. Defina os atributos min, max, step, minlength, maxlength, pattern, required, inputmode e autocomplete conforme apropriado.
  • Se necessário, use um pouco de JavaScript para habilitar validação personalizada e mensagens.
  • Para campos mais complexos, aprimore progressivamente os inputs padrão.

Por fim: esqueça o Internet Explorer!

A menos que seus clientes sejam predominantemente usuários do IE, não há necessidade de implementar suas próprias funções de validação de fallback. Todos os campos de entrada HTML5 funcionam no IE, mas podem exigir mais esforço do usuário. (Por exemplo, o IE não detecta quando você insere um endereço de email inválido.) Você ainda precisa validar dados no servidor, então considere usar isso como base para verificação de erros no IE.

Perguntas Frequentes (FAQs) sobre Formulários HTML e Validação de Restrições

Qual é a importância da validação de formulários HTML?

A validação de formulários HTML é um aspecto crucial do desenvolvimento web. Isso garante que os dados inseridos pelos usuários em um formulário atendam a determinados critérios antes de serem enviados ao servidor. Isso não apenas mantém a integridade dos dados, mas também melhora a experiência do usuário ao fornecer feedback imediato sobre a correção dos dados inseridos. Sem validação de formulários, há risco de receber dados incorretos, incompletos ou mesmo mal-intencionados, o que pode levar a vários problemas, incluindo corrupção de dados, violações de segurança e falhas do sistema.

Como o HTML5 melhora a validação de formulários?

O HTML5 introduz vários novos elementos e atributos de formulário que tornam a validação de formulários muito mais fácil e eficiente. Por exemplo, fornece novos tipos de entrada, como email, URL e número, que validam automaticamente os dados de entrada com base no tipo. Também introduz novos atributos, como required, pattern e min/max, que permitem especificar várias restrições nos dados de entrada. Além disso, o HTML5 fornece uma API de validação integrada que permite realizar validação personalizada usando JavaScript.

Posso realizar a validação de formulários sem JavaScript?

Sim, você pode realizar validação básica de formulários usando apenas o HTML5. O HTML5 fornece vários novos tipos de entrada e atributos que permitem especificar várias restrições nos dados de entrada. Por exemplo, você pode usar o atributo required para tornar um campo obrigatório, o atributo pattern para impor um formato específico e os atributos min/max para definir uma faixa para entrada numérica. No entanto, para validação mais complexa, você ainda pode precisar usar JavaScript.

Como posso personalizar as mensagens de erro na validação de formulários HTML5?

O HTML5 fornece uma API de validação que permite personalizar as mensagens de erro. Você pode usar o método setCustomValidity do objeto ValidityState para definir uma mensagem de erro personalizada para um campo. Este método aceita um argumento de string, que se torna a mensagem de validação do campo quando o campo está inválido. Você pode chamar este método em resposta ao evento invalid, que é disparado quando um campo falha na validação.

Como posso desativar a validação de formulários HTML5?

Você pode desativar a validação de formulários HTML5 adicionando o atributo novalidate ao elemento form. Quando este atributo está presente, o navegador não realizará nenhuma validação no formulário quando ele for enviado. Isso pode ser útil se você quiser lidar com a validação inteiramente no lado do servidor ou usando JavaScript personalizado.

Como posso validar vários campos juntos no HTML5?

HTML5 não fornece uma maneira incorporada de validar vários campos juntos. No entanto, você pode alcançar isso usando JavaScript. Você pode escrever uma função de validação personalizada que verifica os valores de vários campos e define uma mensagem de validade personalizada se eles não atenderem aos critérios necessários. Você pode chamar essa função em resposta ao evento de envio do formulário ou aos eventos de entrada/mudança dos campos.

Como posso validar um campo com base no valor de outro campo em HTML5?

HTML5 não fornece uma maneira incorporada de validar um campo com base no valor de outro campo. No entanto, você pode alcançar isso usando JavaScript. Você pode escrever uma função de validação personalizada que verifica o valor de um campo contra o valor de outro campo e define uma mensagem de validade personalizada se eles não coincidirem. Você pode chamar essa função em resposta aos eventos de entrada/mudança dos campos.

Como posso realizar validação assíncrona em HTML5?

HTML5 não suporta validação assíncrona nativamente. No entanto, você pode alcançar isso usando JavaScript. Você pode escrever uma função de validação personalizada que realiza uma operação assíncrona, como uma solicitação AJAX, e define uma mensagem de validade personalizada com base no resultado. Você pode chamar essa função em resposta aos eventos de entrada/mudança dos campos ou ao evento de envio do formulário.

Como posso estilizar as mensagens de erro na validação de formulários HTML5?

A aparência das mensagens de erro na validação de formulários HTML5 é determinada pelo navegador e não pode ser diretamente estilizada usando CSS. No entanto, você pode criar mensagens de erro personalizadas usando JavaScript e estilizá-las como desejar. Você pode usar a API de validação para determinar quando um campo é inválido e exibir uma mensagem de erro personalizada de acordo.

Como posso testar a validação de um formulário HTML?

Você pode testar a validação de um formulário HTML inserindo vários tipos de dados nos campos e tentando enviar o formulário. Você deve testar com dados válidos e inválidos para garantir que a validação funcione corretamente em todos os casos. Você também pode usar ferramentas ou bibliotecas de teste automatizado para realizar testes mais abrangentes.

Source:
https://www.sitepoint.com/html-forms-constraint-validation-complete-guide/