Angular Reactive Forms Custom Validators[Português]
Tags: angular, reactiveform, validators, portuguese
Published: 2021-03-15 10:43:34

Quando trabalhamos com reactive forms, temos a disposição diversos validators já existentes que vão nos auxiliar na maioria dos nossos casos de uso, mas em diversos momentos necessitamos de validadores customizados, por conta disso esse artigo é para ajudar as pessoas na construção de validadores customizados para suas aplicações.

Os validadores são funções que recebem um form control, verificam se o mesmo corresponde a determinada condição, caso a condição para o form ser válido esteja correta ele retorna um nulo, caso contrário ele retorna um objeto com a chave representando o tipo de validação e um valor true.

Um exemplo de uma função de validação, simples que faz a validação de telefone:

```ts
 phoneNumberValidator(control: AbstractControl): { [s: string]: boolean } {
   const phone = control.value;
   if (phone) {
     if (phone.length == 10 || phone.length == 11) {
       return null;
     } else {
       return { phoneNumberValidator: true };
     }
   }
 }

```
Aplicando o validador:

```ts
 createForm() {
   this.form = new FormGroup({
       'phone': new FormControl(null, [phoneNumberValidator.bind(this)])   
});
```

Esse é um caso simples de um validador extremamente comum em vários formulários, mas imaginem um caso em que eu tenho 2 campos de data em um formulário, data inicial e data final e eu preciso validar se a data final não pode ser anterior a final, como fazer esse validator se eu preciso dos 2 campos para a função?
Nesse caso podemos usar o validator no próprio FormGroup já que a função recebe um AbstractControl como parâmetro.

Um exemplo de como ficaria a função de validação:

```ts
dateOrderCustomValidator(control: AbstractControl) {
   const startDate =  control.value['startDate'];
   const endDate =  control.value['endDate'];
   if (startDate && endDate) {
     if (startDate >= endDate) {
         return { orderDateInvalid: true };
       } else {
         return null;
       }
     } else {
       return null;
     }
 }
```

Aplicando o validador:

```ts
createForm() {
 
   this.form = new FormGroup({ 
 
     'startDate': new FormControl(null),
     'endDate': new FormControl(null)
 
   }, [this.utilsService.dateOrderCustomValidator.bind(this)]);
 
 }
```

Acredito que com esses dois exemplos fique um pouco mais claro, como criar validadores customizados para suas aplicações, os erros podem ser acessados no objeto do formcontrol através da chave errors usando a chave que foi atribuída ao objeto de resposta como identificador.

Exemplo: 

 ```html
<div *ngIf="form.get('phone').errors.phoneNumberValidator">
 Número de telefone inválido
</div>
```

Essa é uma maneira simples e rápida para construir e usar validators custom dentro do angular com reactive forms, podemos usar também a interface ValidatorFn como fica especificado na doc do angular aqui.

Outra sacada interessante para quando se trabalha com validadores customizado é ter um serviço próprio para as funções de validação assim sempre que necessitar de um validador que já foi criado, é só injetar aquele serviço e fazer uso da função de validação.