Angular-Loiane-Training

Este repositorio contem exemplos documentados e descricoes dos conteudos estudados ao longo do curso de Angular da Loiane

View project on GitHub

Validacao Customizada em FormArray

Em form arrays os validadores do angular da classe Validators tambem sao aplicaveis, porem vamos imaginar que seja necessario validar se o usuario selecionou ao menos um checkbox, neste caso nao ha um validador que realize essa verificacao, neste exemplo iremos ver como implementa-la.

para realizar a validacao da quantidade de campos selecionada e necessario criar uma funcao que ira verificar a quantidade de campos marcados como verdadeiro no FormArray, podemos utilizar programacao funcionao e passar a funcao declarada para o motodo array do FormBuilder.

import { HttpClient } from '@angular/common/http';
import { Component, OnInit } from '@angular/core';
import { FormArray, FormBuilder, FormControl, FormGroup, ValidatorFn, Validators } from '@angular/forms';
import { map } from 'rxjs/operators';
import { DadosService } from '../../../shared/dropdown/dados.service';
import { EstadoBr } from './../../../../assets/dados/estados/estados.model';
import { CepService } from './../../../shared/cep/cep.service';

@Component({
  selector: 'app-data-driven-form',
  templateUrl: './data-driven-form.component.html',
  styleUrls: ['./data-driven-form.component.css']
})
export class DataDrivenFormComponent implements OnInit {

  public formulario: FormGroup;
  public estados: EstadoBr[];
  public tecnologias: any[] = this.getTecnologias();
  public newsLetterOptions: any[] = this.getNewsLetter();
  public frameworks = ['Agular', 'React', 'Vue', 'Sencha'];

  constructor(private formBuilder: FormBuilder, private http: HttpClient, private dadosService: DadosService, private cepService: CepService) { }

  ngOnInit(): void {
    this.formulario = this.formBuilder.group({
      nome: [null, Validators.required],
      email: [null, [Validators.required, Validators.email]],
      endereco: this.formBuilder.group({
        cep: [null, Validators.required],
        numero: [null, Validators.required],
        rua: [null, Validators.required],
        complemento: null,
        bairro: [null, Validators.required],
        cidade: [null, Validators.required],
        estado: [null, Validators.required]
      }),
      tecnologias: null,
      newsLetter: null,
      termos: [null, Validators.pattern('true')],
      frameworks: this.buildFormArray()
    })
    this.dadosService.getEstadosBr().subscribe(
      estados => this.estados = estados
    )
    console.log(this.formulario.get('frameworks'));

  }

  public buildFormArray(): FormArray {
    const values = this.frameworks.map(framework => new FormControl(false));
    // passagem do validator para o motodo array
    return this.formBuilder.array(values, this.requiredMinCheckbox());
  }

  // ...demais metodos

  // a variavel validator armazena a arrow function que sera utilizada para realizar a validacao da quantidade minima selecionada no form array.
  public requiredMinCheckbox(min = 1): ValidatorFn {
    const validator = (formulario: FormArray) => {
      const totalChecked = formulario.controls.filter(control => control.value == true).length;
      if(totalChecked < min) return { required: true }
      return null;
    };
    return <ValidatorFn> validator
  }
}

No template HTML basta apenas adicionar os campo de erro e utilizar o metodo aplicaCssErro caso o frameworks, no interior do FormGroup principal seja invalido.

<form class="form-horizontal" [formGroup]="formulario" (ngSubmit)="onSubmit()">
  <div class="form-group">
    
    <!-- adicionado campo de erro e chamada para o metodo aplicaCssErro -->

    <div class="col-md-3" [ngClass]="aplicaCssErro('frameworks')">
      <div id="frameworks">
        <label for="frameworks" class="control-label">Frameworks</label>
        <div id="frameworks">
          <div class="checkbox col-sm-4" formArrayName="frameworks" *ngFor="let control of getFrameworksControls(); let i = index">
            <label>
              <input type="checkbox" [formControlName]="i"> 
            </label>
          </div>
          <app-campo-erro [mostrarErro]="verificaValidAndTouched('frameworks')"
            mensagemErro="selecione pelo menos 1 checkbox">
          </app-campo-erro>
        </div>
      </div>
    </div>
  </div>
  <button type="submit" class="btn btn-primary">Submit</button>
</form>
<app-form-debug [formulario]="formulario"></app-form-debug>


validacao customizada em FormArray.