Resumo: O Validator4D centraliza e padroniza a validação de formulários FMX com API fluente, i18n, máscaras, feedback visual e validação em tempo real opcional. Este guia traz Quick Start, exemplos práticos, receitas de uso, arquitetura e boas práticas.
Quick Start
Em 30 segundos, do zero ao “Salvar com validação”.
uses Validator4D;
var
V: IFormValidator;
procedure TForm1.FormCreate(Sender: TObject);
begin
V := CreateFormValidator
.WithAutoTrim(True)
.WithOnValidated(
procedure(C: TControl; Ok: Boolean; const Msg: string)
begin
// Ex.: trate visualmente aqui (cor do controle/label, etc.)
end);
V.ForControl(EditEmail)
.Required(_('Obrigatório'))
.Email(_('E-mail inválido'))
.WithErrorLabel(LabelEmailErr);
V.AttachOnExit(Self); // ou V.AttachLive(Self) para validar enquanto digita
end;
procedure TForm1.BtnSalvarClick(Sender: TObject);
begin
if V.ValidateAll then
ShowMessage('OK!')
else
ShowMessage('Há campos pendentes.');
end;
Quando usar cada modo
| Modo | Quando usar | Prós | Contras |
|---|---|---|---|
AttachOnExit | Formulários longos / digitação intensa | Menos interrupção ao usuário | Feedback menos imediato |
AttachLive | Campos críticos / máscara / autocompletar | Feedback imediato (com debounce) | Requer debounce (já incluso) |
Motivação (resumo)
Em apps comerciais FMX, validação consistente evita retrabalho e melhora a UX. O Validator4D centraliza regras, padroniza mensagens (i18n) e oferece API fluente com validação em tempo real, reduzindo código repetido e divergências entre telas/equipes. Também facilita manutenção, reutilização e internacionalização (PT/EN/JA).
Exemplos de Uso
1) Básico (obrigatório + e-mail)
V.ForControl(EditEmail)
.Required(_('Obrigatório'))
.Email(_('E-mail inválido'))
.WithErrorLabel(LabelEmailErr);
2) Datas (MinDate/MaxDate/BetweenDates)
uses System.SysUtils, System.DateUtils;
V.ForControl(EditDate)
.DateFormat('yyyy-mm-dd', _('Use AAAA-MM-DD'))
.MinDate(EncodeDate(2025, 1, 1), _('Data mínima: %s'), ['2025-01-01'])
.MaxDate(EncodeDate(2025,12,31), _('Data máxima: %s'), ['2025-12-31'])
.BetweenDates(
EncodeDate(2025, 1, 1),
EncodeDate(2025,12,31),
_('Data fora do intervalo: %s ~ %s'), ['2025-01-01','2025-12-31'])
.WithErrorLabel(LabelDateErr);
3) Horas (MinTime/MaxTime)
EncodeTime(HH, MM, SS, MS)— horas, minutos, segundos, milissegundos. Ex.:EncodeTime(9,0,0,0)= 09:00:00.000.
V.ForControl(EditTime)
.TimeFormat('hh:nn', _('Use HH:MM'))
.MinTime(EncodeTime(9, 0, 0, 0), _('Horário inicial: %s'), ['09:00'])
.MaxTime(EncodeTime(18, 0, 0, 0), _('Horário final: %s'), ['18:00'])
.WithErrorLabel(LabelTimeErr);
4) ListBox e CheckBox
V.ForControl(ListBoxServices)
.MinSelected(1, _('Selecione ao menos 1'))
.MaxSelected(3, _('No máximo 3 itens'));
V.ForControl(ChkTerms)
.Checked(_('É necessário aceitar os termos'));
5) Máscaras rápidas
V.ForControl(EditPhoneJP).Mask('00-0000-0000', _('Telefone inválido'));
V.ForControl(EditCPF).Mask('000.000.000-00', _('CPF inválido'));
6) Regras customizadas
V.ForControl(EditSKU)
.Custom(
procedure(const S: string; var Ok: Boolean; var Msg: string)
begin
Ok := (S <> '') and S.StartsWith('SKU-') and (S.Length = 12);
if not Ok then Msg := _('SKU no formato SKU-XXXXXXXX');
end);
Arquitetura e Fluxo
- Interfaces:
IFormValidator(config/execução) eIValidationRule(regras encadeáveis). - Implementações:
TFormValidatoreTControlRules(mapa controle→regras, cache RTTI, curto-circuito na 1ª falha). - Fluxo de validação:
- Obtenção do texto/valor do controle.
- Auto-trim opcional.
- Campo opcional? (
WhenFilled) → se vazio, pula demais. - Execução sequencial das regras → para na primeira falha.
- Feedback visual (controle/rótulo) + callbacks (
OnValidatedglobal e por controle).
Receitas Rápidas (copy & paste)
Obrigatório condicional
V.ForControl(EditExt)
.When( function: Boolean begin Result := EditBase.Text <> ''; end )
.Required(_('Campo obrigatório quando o outro foi preenchido'));
ComboBox com placeholder (primeiro item)
V.ForControl(CmbCity)
.RequireNonFirst(_('Selecione uma cidade válida'));
URL / E-mail / IP
V.ForControl(EditUrl).URL(_('URL inválida'));
V.ForControl(EditEmail).Email(_('E-mail inválido'));
V.ForControl(EditIP).IPAddress(_('IP inválido'));
Faixa numérica
V.ForControl(EditAge)
.IntegerOnly(_('Apenas números inteiros'))
.Range(18, 99, _('Idade entre %d e %d'), [18, 99]);
Data + Hora compostas
var DT: TDateTime;
DT := EncodeDateTime(2025,10,10,14,0,0,0);
// Valide cada parte e, se necessário, crie regra custom BetweenDateTimes
Internacionalização (i18n)
Use funções _() para resolver mensagens por idioma e suportar placeholders:
function _(const RS: string): string; overload; // retorna idioma atual
function _(const RS: string; const Args: array of const): string; overload;
V.ForControl(EditName)
.MinLen(3, _('Mínimo de %d caracteres'), [3]);
Trocar de idioma = alterar a fonte do _() (dicionário/arquivo/Localizer). Evite concatenação; prefira placeholders.
Feedback Visual e UX
- Rótulos de erro:
.WithErrorLabel(LabelXErr) - Cores: expose/ou use
WithColors(OkColor, ErrorColor)(se disponível) ou trate noOnValidated. - Acessibilidade: mensagens curtas, específicas e coerentes por tela.
Performance
- Debounce embutido no
AttachLivepara evitar validações excessivas. - Regex pré-compiladas e curto-circuito na primeira falha.
- Cache de RTTI para minimizar overhead.
Erros Comuns & Boas Práticas
- RadioButtons: garanta um default válido marcado e
GroupNameconsistente. Em cenários dinâmicos, use helpers:AnyRadioChecked(Group): BooleanEnsureAnyChecked(Group, DefaultRadio)após ocultar/mostrar opções
- ComboBox com placeholder: use
RequireNonFirstpara impedir o “Selecione…”. - ListBox checada: valide quantidade com
MinSelected/MaxSelected. - Máscaras: quando o backend exige formato estrito, combine
Mask+Pattern. - Eventos: o Validator4D injeta handlers preservando os originais.
Extensibilidade
- Regras custom via
.Custom(...). - Novos controles: implemente métodos de obtenção/definição de valor.
- Máscaras: estenda padrões conforme necessidade.
FAQ
Valido antes ou depois do LiveBindings?
Geralmente antes de persistir; com AttachOnExit o usuário corrige campo a campo.
Como validar data + hora juntas?
Monte EncodeDateTime e crie uma regra custom BetweenDateTimes.
E se o campo é opcional?
Use WhenFilled: se vazio, demais regras são puladas.
Conclusão
O Validator4D padroniza a validação em FMX com API fluente, i18n e feedback em tempo real opcional. Você ganha consistência, menos código repetido e uma UX melhor — do simples obrigatório até máscaras e regras complexas. Comece pelo Quick Start, cole as Receitas Rápidas e ajuste as mensagens ao seu idioma e domínio.
Próximos passos: adicione um GIF curto mostrando máscara + erro em label; inclua um quadro “Troubleshooting” com mensagens típicas do backend.