Documentation 14 min read

Advanced Form Validator

Introdução

O Advanced Form Validator é uma biblioteca JavaScript robusta e extensível, projetada para simplificar e aprimorar a validação de formulários HTML em aplicações web. Construída sem dependências externas (Vanilla JS), ela oferece uma API flexível e um conjunto rico de funcionalidades para lidar com diversos cenários de validação, desde regras simples até validações assíncronas complexas e condicionais.

Principais funcionalidades do Advanced Form Validator:

  • Sistema de regras de validação altamente extensível (permite adicionar validadores síncronos e assíncronos personalizados).
  • Regras de validação condicionais baseadas nos dados do formulário.
  • Validação de grupos de campos (ex: grupos de checkboxes ou radio buttons).
  • Suporte avançado a internacionalização (i18n) com placeholders detalhados.
  • Estratégias flexíveis para exibição de erros (integradas e personalizáveis).
  • Acessibilidade aprimorada com atributos ARIA (aria-invalid, aria-describedby).
  • Validação em tempo real com debounce para otimizar performance em eventos de input/change.
  • API baseada em Promises para resultados de validação assíncronos.
  • Métodos abrangentes de ciclo de vida (init, destroy, reset).
  • Rastreamento detalhado do estado de validação de cada campo (valid, invalid, pending, unvalidated).

Características Principais

  • Sistema de Regras Extensível: Adicione facilmente suas próprias regras de validação síncronas ou assíncronas.
  • Validação Condicional: Defina condições para que regras específicas sejam aplicadas apenas quando necessário.
  • Validação de Grupos: Valide campos como grupos (ex: exigir um número mínimo de checkboxes marcados).
  • Internacionalização (i18n): Forneça mensagens de erro em múltiplos idiomas e personalize-as facilmente.
  • Exibição de Erros Flexível: Escolha como e onde os erros são exibidos (antes/depois do campo, dentro de um container) ou implemente sua própria lógica.
  • Acessibilidade (ARIA): Atualiza automaticamente atributos ARIA para indicar o estado de validação dos campos.
  • Validação em Tempo Real (Debounced): Valida campos enquanto o usuário digita (com debounce configurável) para feedback imediato sem sobrecarregar.
  • API Assíncrona (Promises): Os métodos de validação retornam Promises, facilitando a integração com fluxos assíncronos.
  • Manipulador de Submissão: Forneça uma função submitHandler personalizada para controlar o que acontece após a validação bem-sucedida.
  • Controle de Foco e Scroll: Opções para focar automaticamente no primeiro campo inválido e/ou rolar a página até ele após a submissão falhar.
  • Sem Dependências: Funciona puramente com JavaScript Vanilla.
  • Gerenciamento de Estado: Métodos para obter o estado de validação de campos individuais ou do formulário inteiro.

Instalação

Para usar o Advanced Form Validator, siga os passos abaixo:

1. Inclua o Script

Adicione o script JavaScript no seu HTML, preferencialmente antes do fechamento da tag </body>:

<script src="https://cdn.alphasystem.dev/plugins/advanced-form-validator/latest/script-min.js"></script>

2. Inicialize a Biblioteca

O Advanced Form Validator não inicializa automaticamente. Você precisa criar uma instância da classe AdvancedFormValidator, passando o elemento do formulário (ou seletor), a configuração de validação e, opcionalmente, um objeto de opções.

Inicialização Básica:

// Espera o DOM carregar
document.addEventListener('DOMContentLoaded', () => {
	const myForm = document.getElementById('meu-formulario');

	// Define as regras de validação
	const validationConfig = {
		nomeUsuario: [
			{ type: 'required', message: 'O nome de usuário é obrigatório.' },
			{ type: 'minLength', value: 5 }
		],
		email: [
			{ type: 'required' },
			{ type: 'email' }
		],
		honeypot: [ // Exemplo de campo honeypot
			{ type: 'honeypot' } // Campo deve ser vazio para passar na validação.
		]
		// ... outras regras para outros campos
	};

	// Cria a instância do validador
	const validator = new AdvancedFormValidator(myForm, validationConfig);

	console.log('Validador inicializado!');
});

Inicialização com Opções:

document.addEventListener('DOMContentLoaded', () => {
	const myForm = '#meu-formulario'; // Pode usar seletor CSS

	const validationConfig = {
		// ... regras ...
		email: [ { type: 'required' }, { type: 'email' } ],
		senha: [ { type: 'required' }, { type: 'passwordStrength', value: 4 }]
	};

	const validatorOptions = {
		validateOnInput: true, // Validar enquanto digita
		inputDebounce: 400,   // Atraso para validação no input
		containerSelector: '.form-group', // Onde exibir erros e aplicar classes de estado
		submitHandler: (form, event, validatorInstance) => {
			console.log('Formulário válido! Enviando dados...');
			// Lógica de envio customizada aqui
			// Ex: Enviar dados via fetch/axios
			// form.submit(); // Para submissão padrão (se necessário)
		},
		defaultLanguage: 'pt-br', // Definir idioma padrão
		i18n: {
			'pt-br': { // Sobrescrever ou adicionar mensagens pt-br
				required: 'Este campo não pode ficar vazio.',
				email: 'Por favor, insira um e-mail válido.',
				passwordStrength: 'Sua senha precisa de: {details}.'
			}
		}
	};

	const validator = new AdvancedFormValidator(myForm, validationConfig, validatorOptions);
});

Configuração

O Advanced Form Validator é configurado principalmente através do construtor new AdvancedFormValidator(formElementOrSelector, config, options).

  1. formElementOrSelector: (HTMLFormElement | String) O elemento form a ser validado ou um seletor CSS para encontrá-lo.
  2. config: (Object | Array) A configuração das regras de validação. Pode ser:
    • Um objeto onde as chaves são os nomes (name ou id) dos campos e os valores são arrays de objetos de regra (ValidatorRuleInstance).
    • Um array de objetos no formato { field: 'fieldName', rules: [ruleInstance1, ...] }.
  3. options: (Object, opcional) Um objeto para personalizar o comportamento do validador. As principais opções são:
    • errorClass: (String) Classe CSS para o elemento que exibe a mensagem de erro. Padrão: 'validator-error'.
    • errorFieldClass: (String) Classe CSS adicionada ao campo inválido (ou ao container, dependendo do campo). Padrão: 'field-error'.
    • validFieldClass: (String) Classe CSS adicionada ao campo válido (ou container). Padrão: 'field-valid'.
    • pendingFieldClass: (String) Classe CSS adicionada durante validação assíncrona. Padrão: 'field-pending'.
    • errorElementTag: (String) Tag HTML para o elemento de erro. Padrão: 'div'.
    • containerSelector: (String | null) Seletor CSS (relativo ao campo) para encontrar o container onde o erro deve ser exibido e as classes de estado aplicadas (ex: '.form-group'). Se null, o validador tenta encontrar um container lógico (como um elemento com classe .form-group, um fieldset, ou o parentElement do campo). Padrão: null.
    • errorDisplayStrategy: (String | Function) Como exibir o erro: 'afterField' (padrão), 'beforeField', 'appendToContainer', ou uma função customizada.
    • validateOnInit: (Boolean) Validar o formulário imediatamente na inicialização. Padrão: false.
    • validateOnInput: (Boolean) Habilitar validação em tempo real nos eventos input ou change. Padrão: true.
    • inputDebounce: (Number) Atraso (ms) para a validação em tempo real. Padrão: 350.
    • focusOnError: (Boolean) Focar no primeiro campo inválido após tentativa de submissão. Padrão: true.
    • scrollOnError: (Boolean) Rolar até o primeiro campo inválido. Padrão: true. O comportamento do scroll é definido por scrollOptions.
    • scrollOptions: (Object) Opções passadas para element.scrollIntoView(). Padrão: { behavior: 'smooth', block: 'center' }.
    • submitHandler: (Function | null) Callback (form, event, validatorInstance) chamado se a validação for bem-sucedida na submissão. Se definido, previne a submissão padrão do formulário. Padrão: null.
    • i18n: (Object) Objeto para sobrescrever ou adicionar pacotes de idiomas. Formato: { langCode: { ruleType: message, ... }, ... }. Padrão: {}.
    • defaultLanguage: (String) Código do idioma padrão a ser usado das mensagens. Padrão: 'en'.

Estrutura de uma Regra (ValidatorRuleInstance)

{
	type: 'required', // Nome da regra (string, obrigatório)
	value: 5,         // Parâmetro da regra (opcional, depende da regra, ex: minLength)
	message: 'Mínimo de {value} caracteres necessários.', // Mensagem customizada (opcional)
	condition: (formData, validator) => formData.campoX === 'valorY', // Função condicional (opcional)
	details: 'detalhes extras para a senha' // Detalhes para placeholders como {details} (opcional, ex: para passwordStrength)
}

Uso e Integração

Após configurar e instanciar o validador, ele funcionará automaticamente com base nas opções.

Definindo Regras

A parte mais importante é definir o objeto config corretamente, mapeando os nomes dos campos (atributo name ou id) para um array de regras a serem aplicadas.

const validationConfig = {
	// Campo 'username' (pode ser ID ou Name)
	username: [
		{ type: 'required' }, // Regra obrigatória
		{ type: 'minLength', value: 3, message: 'Usuário muito curto (mínimo {value}).' },
		{ type: 'maxLength', value: 20 }
	],
	// Campo 'email'
	email: [
		{ type: 'required' },
		{ type: 'email' }
	],
	// Campo 'idade' com condição
	idade: [
		{ type: 'required' },
		{ type: 'integer' },
		{
			type: 'min',
			value: 18,
			// Só aplica a regra 'min' se o checkbox 'aceitaTermos' estiver marcado
			condition: (formData) => formData.aceitaTermos === true // getFormData() retorna boolean para checkboxes únicos
		}
	],
	// Grupo de checkboxes 'interesses' (usar o 'name' do grupo)
	interesses: [
		{ type: 'groupRequired', value: 2, message: 'Selecione ao menos {value} interesses.' }
	],
	// Senha e confirmação
	senha: [
		{ type: 'required' },
		{ type: 'passwordStrength', value: { level: 3, minLength: 8 } } // Nível de força e comprimento mínimo
	],
	confirmarSenha: [
		{ type: 'required' },
		{ type: 'match', value: 'senha' } // Deve corresponder ao campo 'senha'
	],
	// Campo Honeypot para anti-spam
	feedbackInvisivel: [
	    { type: 'honeypot' }
	]
};

Regras Pré-Definidas

O Advanced Form Validator vem com um conjunto abrangente de regras de validação pré-definidas, que você pode utilizar diretamente ou customizar conforme necessário. Segue uma breve descrição de cada regra incorporada:

required:
Garante que o campo não esteja vazio. Esta regra é fundamental e verifica a presença de um valor.

email:
Verifica se o valor informado corresponde a um formato válido de e-mail.

minLength:
Assegura que o número de caracteres do valor seja, no mínimo, o especificado (por exemplo, { type: 'minLength', value: 5 }).

maxLength:
Garante que o número de caracteres do valor não exceda o limite especificado.

pattern:
Valida o valor contra uma expressão regular (RegExp) fornecida.

number:
Confirma se o valor informado é um número válido, permitindo casas decimais.

integer:
Verifica se o valor é um número inteiro.

range:
Valida se um valor numérico está dentro de um intervalo especificado (com parâmetros min e max, ex: { type: 'range', value: { min: 10, max: 20 } }).

min:
Exige que o valor numérico seja maior ou igual ao valor configurado.

max:
Exige que o valor numérico seja menor ou igual ao valor configurado.

url:
Valida se o valor corresponde a um formato válido de URL.

match:
Compara o valor de um campo com o de outro campo, geralmente usado para confirmação (ex: senha e confirmar senha). O parâmetro `value` é o nome/id do campo a ser comparado.

checked:
Geralmente utilizada para checkboxes, certifica-se de que o campo esteja marcado.

groupRequired:
Valida grupos de campos (como múltiplos checkboxes com o mesmo `name`) para assegurar que pelo menos um número mínimo de opções (`value`) esteja selecionado.

passwordStrength:
Avalia a força de uma senha. O parâmetro `value` da regra pode ser um número (nível de força 1-5, onde 5 é o mais forte, e os critérios padrão são comprimento >= 8, minúsculas, maiúsculas, números e símbolos) ou um objeto para configuração detalhada (ex: `{ level: 3, minLength: 10, requireUppercase: true, requireDigit: false }`). A mensagem de erro com o placeholder `{details}` listará os critérios ativos.

honeypot:
Esta regra é usada para combater spam por bots. Ela garante que o campo designado permaneça vazio. Se o campo for preenchido, a validação falhará.

Você pode usar estas regras diretamente na configuração ao instanciar o validador. Além disso, novas regras customizadas podem ser adicionadas utilizando o método addRule.

Validação na Submissão

A validação ocorre automaticamente quando o formulário é submetido.

  • Se válido e submitHandler não for definido, o formulário é submetido normalmente.
  • Se válido e submitHandler for definido, a função submitHandler é chamada, e a submissão padrão é prevenida.
  • Se inválido, a submissão é prevenida, os erros são exibidos, e o foco/scroll (se habilitados) são acionados.

Validação em Tempo Real

Se validateOnInput: true, os campos serão validados enquanto o usuário interage (eventos input ou change, com debounce).

Adicionando Regras Customizadas

Use o método addRule para definir novas regras.

// Adiciona uma regra síncrona customizada
validator.addRule({
	type: 'startsWithA', // Nome da nova regra
	validateSync: (value, element, param) => {
		if (!value) return true; // Permite vazio (a menos que 'required' seja usado)
		return String(value).toLowerCase().startsWith('a');
	},
	defaultMessage: 'O valor deve começar com a letra A.'
});

// Adiciona uma regra assíncrona customizada (ex: verificar disponibilidade de username)
validator.addRule({
	type: 'usernameAvailable',
	validateAsync: async (value, element, param) => {
		if (!value) return true;
		try {
			const response = await fetch(`/api/check-username?username=${encodeURIComponent(value)}`);
			if (!response.ok) throw new Error(`HTTP error! status: ${response.status}`);
			const data = await response.json();
			return data.isAvailable; // API deve retornar { isAvailable: true/false }
		} catch (error) {
			console.error('Erro na validação assíncrona:', error);
			return false; // Falha na validação se a API falhar
		}
	},
	defaultMessage: 'Este nome de usuário já está em uso.'
});

// Agora você pode usar 'startsWithA' e 'usernameAvailable' na sua config:
const newConfig = {
	// ... (supondo que 'validator' já foi instanciado)
	// Para aplicar a nova regra, você normalmente a adicionaria antes da instanciação
	// ou, se a instância já existe e você precisa modificar,
	// seria necessário um método para atualizar a configuração interna
	// e rebindar eventos, o que não é padrão.
	// O ideal é adicionar todas as regras customizadas antes de criar a instância do validador.
};

// Exemplo de uso em uma nova instância:
// validator.addRule(...); // Adiciona as regras customizadas primeiro
// const anotherValidator = new AdvancedFormValidator(form, {
//   apelido: [ { type: 'startsWithA' } ],
//   novoUsuario: [ { type: 'required' }, { type: 'usernameAvailable' } ]
// });

Nota: É melhor definir regras customizadas globalmente (se possível, antes de qualquer instanciação) ou adicionar à instância específica logo após sua criação, antes que as validações comecem. Modificar regras em uma instância já ativa e em uso pode exigir reinicialização ou gerenciamento cuidadoso do estado.

Resetando a Validação

Para limpar os erros e o estado de validação (sem limpar os valores dos campos):

validator.reset();

Para limpar também os valores dos campos, use o reset nativo do formulário junto:

const myFormElement = document.getElementById('meu-formulario');
myFormElement.reset(); // Limpa valores
validator.reset();     // Limpa estado de validação

Destruindo a Instância

Para remover todos os event listeners e limpar o estado:

validator.destroy();

Referência da API

Construtor

  • new AdvancedFormValidator(formElementOrSelector, config, options?): Cria uma nova instância do validador.
    • Parâmetros:
      • formElementOrSelector (HTMLFormElement | String): O formulário ou seletor.
      • config (Object | Array): Configuração das regras.
      • options (Object, opcional): Opções de personalização.
    • Retorna: Instância de AdvancedFormValidator.

Métodos Principais

  • validate(): Valida o formulário inteiro manualmente.
    • Retorna: Promise<boolean> - Resolve para true se válido, false caso contrário.
  • validateField(fieldName): Valida um campo específico manualmente.
    • Parâmetros:
      • fieldName (String): O name ou id do campo.
    • Retorna: Promise<boolean> - Resolve para true se válido, false caso contrário.
  • addRule(ruleDefinition): Adiciona uma definição de regra customizada à instância do validador.
    • Parâmetros:
      • ruleDefinition (Object): Objeto definindo a regra (type, validateSync/validateAsync, defaultMessage, etc.).
    • Retorna: void.
  • reset(): Limpa todos os erros, classes de estado e redefine o status dos campos para 'unvalidated'. Não limpa os valores dos campos.
    • Retorna: void.
  • destroy(): Remove event listeners, limpa erros e redefine o estado interno. Torna a instância inativa.
    • Retorna: void.
  • getFormData(): Obtém os dados atuais do formulário como um objeto chave-valor. Lida com checkboxes (únicos e grupos) e selects múltiplos.
    • Retorna: Object.
  • getErrors(): Retorna um objeto com os erros de validação atuais.
    • Retorna: Object.<string, string> - Mapeamento de fieldName para errorMessage.
  • getFieldStatus(fieldName): Retorna o status de validação atual de um campo.
    • Parâmetros:
      • fieldName (String): O nome do campo.
    • Retorna: 'valid' | 'invalid' | 'pending' | 'unvalidated'.
  • getAllFieldStatuses(): Retorna um objeto com o status de todos os campos configurados.
    • Retorna: Object.<string, ('valid' | 'invalid' | 'pending' | 'unvalidated')>.
  • isValid(): Verifica se todos os campos configurados no validador estão atualmente no estado 'valid'. Retorna true se todos os campos configurados passaram na validação, false caso contrário. Um formulário sem campos configurados é considerado válido.
    • Retorna: boolean.
  • isFieldValid(fieldName): Verifica se um campo específico é considerado válido.
    • Parâmetros:
      • fieldName (String): O nome do campo.
    • Retorna: boolean.
  • setLanguage(langCode): Altera o idioma atual para as mensagens de erro.
    • Parâmetros:
      • langCode (String): O código do idioma (ex: 'en', 'pt-br') que deve existir nas mensagens configuradas (DEFAULT_MESSAGES ou options.i18n).
    • Retorna: void.

Propriedades (Acesso via Métodos Recomendado)

  • errors: Objeto interno de erros (use getErrors()).
  • fieldStatus: Objeto interno de status (use getFieldStatus() / getAllFieldStatuses()).
  • options: Objeto de opções usado pela instância.
  • messages: Objeto de mensagens de erro (combinado de padrões e i18n).
  • currentLang: Código do idioma atual.

Resolução de Problemas

  • AdvancedFormValidator is not defined: Verifique se o script foi incluído corretamente no HTML antes de tentar usar new AdvancedFormValidator(...) e se o DOM está carregado.
  • Validação não funciona / Erros não aparecem:
    • Confira se o seletor do formulário está correto e se o elemento existe no DOM no momento da inicialização.
    • Verifique se os nomes/IDs dos campos na config correspondem exatamente aos atributos name ou id dos elementos HTML.
    • Confirme se as regras estão definidas corretamente (type existe, value fornecido se requiresParam: true).
    • Verifique se o containerSelector (se usado) está correto e se os elementos container existem e são acessíveis a partir do campo.
    • Inspecione o console do navegador por erros de JavaScript.
    • Verifique se as classes CSS (errorClass, errorFieldClass) estão definidas no seu CSS para que os erros e estados sejam visualmente aparentes.
  • Validação assíncrona (async) não funciona:
    • Certifique-se de que a função asyncValidator retorna uma Promise que resolve para true (válido) ou false (inválido).
    • Verifique a aba "Rede" (Network) do console do navegador e o console por erros na requisição (se aplicável).
    • A classe field-pending (definida em pendingFieldClass) deve ser estilizada se desejar feedback visual durante a espera da validação assíncrona.
  • submitHandler não é chamado:
    • O submitHandler só é chamado se a validação for 100% bem-sucedida para todos os campos configurados. Verifique se há erros ocultos usando validator.getErrors() ou inspecionando o console.
  • Validação em tempo real (validateOnInput) muito lenta/rápida:
    • Ajuste a opção inputDebounce (valor maior = menos validações, porém com mais atraso; valor menor = validações mais frequentes, potencialmente mais rápido o feedback, mas pode impactar performance em validações complexas).
  • Mensagens de erro não mudam com setLanguage:
    • Verifique se o langCode passado para setLanguage existe no objeto messages da instância (seja nos padrões ou no options.i18n).
    • O validador tenta automaticamente atualizar as mensagens de erro já exibidas ao trocar o idioma. Se isso não ocorrer, verifique se há erros no console.