Renê Silva Lima
Renê Silva Lima

Reputation: 2805

Conditional Validation Angular 2 - Model Driven Forms

I have a form in Angular 2 in which I have a checkbox that changes some input[text] on the page. If the checkbox is checked an input that is called 'CPF' is changed to 'CNPJ'. I need CNPJ to be required only if the checkbox is checked since the user will not even see the 'CNPJ' input if its not checked.

Here's a snippet from the HTML code:

    <div class="wrap-acordo">
  <form [formGroup]="formDadosBancarios" novalidate class="" (ngSubmit)="enviarDados(formDadosBancarios.value)">

  <div class="row">
    <div class="col s12">
      <label> Titular: </label>
      <input type="text" formControlName="titular" name="titular" class="forms-econ" placeholder="Nome Completo do Titular">
         <div class="div-validar">
            <span [hidden]="formDadosBancarios.get('titular').hasError('required') || formDadosBancarios.controls.titular.valid || (formDadosBancarios.controls.titular.pristine && !submitted)">
              Titular Inválido (mínimo 3 caracteres).
            </span>
          <span *ngIf="formDadosBancarios.get('titular').hasError('required') && submitted">
            Campo titular obrigatório
          </span><br>
        </div>
    </div>
    <p class="check-margin">
      <input type="checkbox" [checked]="" formControlName="pessoa_juridica" #checkJuridica (change)="handleType(checkJuridica.checked)" class="filled-in check-negociacao" id="pessoaJuridica" />
      <label for="pessoaJuridica">Pessoa Jurídica</label>
    </p>
    <div *ngIf="checkJuridica.checked" class="col s12">
      <label> CNPJ: </label>
      <input type="text" formControlName="cnpj" name="cnpj" class="forms-econ" placeholder="Insira o CNPJ">
        <div class="div-validar">
          <span [hidden]="formDadosBancarios.get('cnpj').hasError('required') || formDadosBancarios.controls.cnpj.valid || (formDadosBancarios.controls.cnpj.pristine && !submitted)">
            CNPJ inválido
          </span>
          <span *ngIf="formDadosBancarios.get('cnpj').hasError('required') && submitted">
            CNPJ é obrigatório
          </span><br>
        </div>
    </div>
    <div *ngIf="!checkJuridica.checked" class="col s12 m6">
      <label> CPF: </label>
      <input type="text" formControlName="cpf" name="cpf" class="forms-econ" placeholder="Insira seu CPF">
        <div class="div-validar">
          <span [hidden]="formDadosBancarios.get('cpf').hasError('required') || formDadosBancarios.controls.cpf.valid || (formDadosBancarios.controls.cpf.pristine && !submitted)">
            CPF inválido
          </span>
          <span *ngIf="formDadosBancarios.get('cpf').hasError('required') && submitted">
            CPF é obrigatório
          </span><br>
        </div>
    </div>
    <div *ngIf="!checkJuridica.checked" class="col s12 m6">
      <label> Data de Nascimento: </label>
      <input type="text" class="forms-econ" formControlName="data_nasc" name="data_nasc" placeholder="ex.: Insira sua data de nascimento">
        <div class="div-validar">
          <span [hidden]="formDadosBancarios.controls.data_nasc.valid || (formDadosBancarios.controls.data_nasc.pristine && !submitted)">
            Data de nascimento é obrigatório
          </span>
        </div>
    </div>
    <div class="col s12 m6">
      <label> Banco: </label>
      <input type="text" class="forms-econ" formControlName="banco" name="banco" placeholder="Banco">
      <div class="div-validar">
        <span [hidden]="formDadosBancarios.controls.banco.valid || (formDadosBancarios.controls.banco.pristine && !submitted)">
         Banco é um campo obrigatório
        </span>
      </div>
    </div>
    <div class="col s12 m6">
      <label> Agência: </label>
      <input type="text" class="forms-econ" formControlName="agencia" name="agencia" placeholder="Agência">
       <div class="div-validar">
         <span [hidden]="formDadosBancarios.controls.agencia.valid || (formDadosBancarios.controls.agencia.pristine && !submitted)">
           Agência é um campo obrigatório
         </span>
       </div>
    </div>
    <div class="col s12 m6">
      <label> Conta: </label>
      <input type="text" class="forms-econ" name="conta" formControlName="conta" placeholder="Conta">
       <div class="div-validar">
         <span [hidden]="formDadosBancarios.controls.conta.valid || (formDadosBancarios.controls.conta.pristine && !submitted)">
           Conta é um campo obrigatório
         </span>
      </div>
    </div>
    <div class="col s12 m6">
      <label> Tipo: </label>
        <select name="tipo" formControlName="tipo" class="forms-econ">
          <option value="motivo_01">Tipo 01</option>
          <option value="motivo_02">Tipo 02</option>
        </select>
       <div class="div-validar">
         <span [hidden]="formDadosBancarios.controls.tipo.valid || (formDadosBancarios.controls.tipo.pristine && !submitted)">
           Tipo é um campo obrigatório
         </span>
       </div>
    </div>
  </div>
  <div class="row center-align">
    <div class="col s12 m6">
      <input type="submit" class="botao-medio btn-aceita" value="Aceitar">
    </div>

and here's a snippet from the component's code:

  import { Component } from '@angular/core';
import {Http} from '@angular/http';
import { FormBuilder, FormGroup, Validators, FormArray, FormsModule, ReactiveFormsModule, AbstractControl, ValidatorFn } from '@angular/forms';
import {FinalizaNegociacaoService} from '../services/finaliza-negociacao.service';
import {dadosAcordo} from '../model/dados-acordo.interface';

@Component({
  moduleId: module.id,
  selector: 'detalhes',
  templateUrl: `finaliza-negociacao.component.html`,
  providers: [FinalizaNegociacaoService]
})

    export class FinalizaNegociacaoComponent  {

      public dados:dadosAcordo;
      public formDadosBancarios: FormGroup;

      public submitted: boolean; 
      public events: any[] = []; 
      public servError:any;
      public servSuccess:any;  
      cpf_REGEXP =  /^\d+$/;

      constructor(private _fb: FormBuilder, private finalizaAcordo:FinalizaNegociacaoService) { } 

        ngOnInit() {  
          this.formDadosBancarios = this._fb.group({
            titular: ['', [<any>Validators.required, <any>Validators.minLength(3)]],
            cpf: ['', [<any>Validators.required, Validators.pattern(this.cpf_REGEXP)]], 
            cnpj: ['', [<any>Validators.required, Validators.pattern(this.cpf_REGEXP)]],
            data_nasc: ['', <any>Validators.required],
            agencia: ['', <any>Validators.required ],
            banco: ['', <any>Validators.required],
            conta: ['', <any>Validators.required],
            tipo:  ['', <any>Validators.required],
            id: ['']
          })      
        }
    enviarDados(model: dadosAcordo, isValid: boolean) {
        this.submitted = true; 
        model.id = Math.floor((Math.random()*100));
        if(this.formDadosBancarios.valid){
          console.log("valid form")
         this.finalizaAcordo.enviaDadosBancarios(model)
          .subscribe(
            res => console.log("Sucesso"),
            error => console.log("ERRO")
          );
        }else{
          console.log("invalid form")
        }
      }

Can someone help me? Thanks in advance :)

Upvotes: 1

Views: 711

Answers (2)

developer033
developer033

Reputation: 24864

You can do the following:

  1. Create a method to handle the changes of your checkbox:
handleType(isJuridica: boolean): void {
  const cpfCtrl: AbstractControl = this.formDadosBancarios.get('cpf');
  const cnpjCtrl: AbstractControl = this.formDadosBancarios.get('cnpj');
  const reqValidators: ValidatorFn[] = [Validators.required, Validators.pattern(this.cpf_REGEXP)];
  const nullValidator: ValidatorFn = Validators.nullValidator;

  // Set validators accordingly
  if (isJuridica) {
    cpfCtrl.setValidators(nullValidator);
    cnpjCtrl.setValidators(reqValidators);
  } else {
    cpfCtrl.setValidators(reqValidators);
    cnpjCtrl.setValidators(nullValidator);
  }

  // Clean values (if you want to)
  cpfCtrl.patchValue('');
  cnpjCtrl.patchValue('');
  cpfCtrl.updateValueAndValidity();
  cnpjCtrl.updateValueAndValidity();
}
  1. Call it in template:
...
<input type="checkbox" #checkJuridica (change)="handleType(checkJuridica.checked)" class="filled-in check-negociacao" id="pessoaJuridica" />
<label for="pessoaJuridica">Pessoa Jurídica</label>
...

You can check a simple demo below:

PLUNKER

In addition, there is this tutorial which can help you to understand better.

Upvotes: 2

Pardeep Jain
Pardeep Jain

Reputation: 86720

your code is bit complicated but i'll give you tip,may help you to solve your problem.

  • no need to add validators.required on conditional field like cpf or cnpj, else you have to add validation on event fired on checkbox click.

  • if you have to disable submit button (in this case better is to call function in disabled attribut like this [disabled]=''checkValidation() and check there your all required fields.

i hope this will put some light on your problem if still not please post full code either recreate your problem on plunker.

Upvotes: 1

Related Questions