Pular para o conteúdo principal

Validação

O SchemaForms suporta três camadas de validação:

  1. Regras nativasobrigatorio, validacao (minLength, regex, data, etc.)
  2. Validadores customizados — funções assíncronas registradas em validatorMapper, referenciadas pelo schema
  3. Avisos — igual aos validadores, mas apenas informativos (não bloqueiam o envio)

Regras de validação nativas

Configuradas via FormField.validacao:

interface FieldValidation {
minLength?: number;
maxLength?: number;
min?: number; // valor numérico mínimo
max?: number; // valor numérico máximo
regex?: string; // padrão regex
regexMessage?: string; // mensagem quando o regex falha
minDate?: string; // string de data ISO
maxDate?: string;
fileTypes?: string[]; // ['image/png', 'image/jpeg']
maxFileSize?: number; // bytes
minAge?: number; // idade mínima em anos (campos DATE)
maxAge?: number;
}

Exemplo no JSON do schema:

{
"nome": "bio",
"tipo": "textarea",
"validacao": {
"minLength": 20,
"maxLength": 500
}
}

Validadores customizados (validate[])

Para validação que não pode ser expressa como regra estática — verificações assíncronas, validação entre campos, chamadas a APIs externas.

1. Registrar funções validadoras

Passe um validatorMapper para o <FormRenderer>:

import { FormRenderer } from "@schema-forms-data/renderer";

<FormRenderer
schema={schema}
validatorMapper={{
// Assíncrono: verificar unicidade do e-mail
emailUnico: async (value) => {
const exists = await api.checkEmail(String(value));
return exists ? "E-mail já cadastrado" : undefined;
},

// Entre campos: comparar com o valor de outro campo
senhasIguais: (value, allValues, config) => {
const other = allValues[config["field"] as string];
return value === other ? undefined : "As senhas não coincidem";
},

// Com parâmetros extras da configuração do schema
minIdade: (value, _all, config) => {
const age = getAgeFromDate(String(value));
const min = (config["min"] as number) ?? 18;
return age >= min ? undefined : `Deve ter pelo menos ${min} anos`;
},
}}
onComplete={handleComplete}
/>;

2. Referenciar no schema

Adicione um array validate a qualquer FormField:

{
"nome": "email",
"tipo": "email",
"obrigatorio": true,
"validate": [
{ "type": "emailUnico", "message": "Este e-mail já está em uso" }
]
}
{
"nome": "confirmacao_senha",
"tipo": "password",
"validate": [{ "type": "senhasIguais", "field": "senha" }]
}
{
"nome": "data_nascimento",
"tipo": "date",
"validate": [
{
"type": "minIdade",
"min": 16,
"message": "Deve ter pelo menos 16 anos"
}
]
}

Assinatura da função validadora

type FieldValidatorFn = (
value: unknown,
allValues: Record<string, unknown>, // todos os valores do passo atual
config: FieldValidatorConfig, // { type, message, ...parâmetros extras }
externalData: Record<string, unknown>, // prop externalData
) => string | undefined | Promise<string | undefined>;

Retorne undefined se válido, ou uma string com a mensagem de erro se inválido. A message na configuração do schema (se definida) substitui a string retornada pela função.

Múltiplos validadores em sequência

Os validadores rodam em ordem — o primeiro que retornar uma mensagem de erro interrompe a cadeia:

{
"nome": "cpf",
"tipo": "cpf",
"validate": [
{ "type": "cpfValido" },
{ "type": "cpfUnico", "message": "CPF já cadastrado" }
]
}

Avisos (warn[])

Igual ao validate[], mas as mensagens não bloqueiam o envio — são apenas informativas. Os avisos estão disponíveis via:

  • useFormState().warnings
  • useField(name).warning
  • useRendererContext().fieldWarnings

Exemplo

<FormRenderer
schema={schema}
validatorMapper={{
senhaFraca: (value) => {
const s = String(value);
if (s.length < 8) return "Senha fraca — use pelo menos 8 caracteres";
if (!/[A-Z]/.test(s)) return "Considere adicionar uma letra maiúscula";
return undefined;
},
}}
onComplete={handleComplete}
/>

Schema:

{
"nome": "senha",
"tipo": "password",
"obrigatorio": true,
"warn": [{ "type": "senhaFraca" }]
}

O aviso é exibido ao usuário, mas ele ainda pode clicar em Enviar.

Exemplo de validação entre campos

validatorMapper={{
dataFimAposInicio: (value, allValues) => {
const inicio = allValues["data_inicio"] as string;
if (!inicio || !value) return undefined;
return new Date(value as string) > new Date(inicio)
? undefined
: "A data de fim deve ser posterior à data de início";
},
}}

Schema:

{
"nome": "data_fim",
"tipo": "date",
"validate": [{ "type": "dataFimAposInicio" }]
}