Validação
O SchemaForms suporta três camadas de validação:
- Regras nativas —
obrigatorio,validacao(minLength, regex, data, etc.) - Validadores customizados — funções assíncronas registradas em
validatorMapper, referenciadas pelo schema - 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().warningsuseField(name).warninguseRendererContext().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" }]
}