简体   繁体   中英

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 :)

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.

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM