Search code examples
javascriptangularformsvalidationangular-forms

Angular 4 how to show hide nested Form Group validation


I am working on angular 4 validation. I have a reactive form that have two radio button and two form groups. If user select's first radio button, it will remove validation from second form group and add validation on first form group and when select's second radio button it will add validation on second form group and remove from first form group.

Below is my form group example

this.mainForm = this.formBuilder.group({
    cardOrBank: new FormControl(''),
    cardDetails: new FormGroup({
        cardNo: new FormControl(''),
        cvv: new FormControl('')
    }),
    bankDetails: new FormGroup({
        accNo: new FormControl(''),
        ifsc: new FormControl('')
    })
});

HTML

<form [formGroup]="mainForm" (ngSubmit)="onFormSubmit()">
    <div>
        Select: <input type="radio" formControlName="cardOrBank"> card
        <input type="radio" formControlName="cardOrBank"> bank
    </div>
    <div formGroupName="cardDetails">
        <div>
            Card No: <input formControlName="cardNo">
        </div>
        <div>
            CVV: <input formControlName="cvv">
        </div>
    </div>
    <div formGroupName="bankDetails">
        <div>
            ACC No: <input formControlName="accNo">
        </div>
        <div>
            IFSC: <input formControlName="ifsc">
        </div>
    </div>
    <div>
        <button type="submit">Submit</button>
    </div>
</form>

If select card from radio button, it will add validation on cardDetails form and remove validation from bankDetails and vice versa.

P.S: Form fields may be more according to the requirement.

Thanks.


Solution

  • After doing a lot of work finally i was able to achieve this.

    Below are the changes you need to make in your code :

    // in component.ts file  : 
    
    
    // Write two genric methods which sets and clears the validator 
    
    setRequireValidator(form:any){
      for (const field in form.controls) { // 'field' is a string
       let con = form.get(field); // 'control' is a FormControl
        con.setValidators([Validators.required]);
        con.updateValueAndValidity();
    }
    
    }
    
    removeValidator(form:any){
      console.log('form contro',form);
      
      for (const field in form.controls) { // 'field' is a string
       let con = form.get(field); // 'control' is a FormControl
        con.clearValidators();
        con.updateValueAndValidity();
    }
      
     
     // while initiallizing the form ragister the event for value changed on `cardOrBank`
    
    // check which value user has selected and accordingly toggle between them 
    
    
     this.mainForm.get('cardOrBank').valueChanges.subscribe((val) => {
            const cardControl = this.mainForm.get('cardDetails');
            const bankControl = this.mainForm.get('bankDetails');
               if(val === 'card') {
               alert('card sletecd')
               this.removeValidator(bankControl);
              this.setRequireValidator(cardControl);
    
            } else{
                 alert('bank sletecd')
              this.removeValidator(cardControl);
              this.setRequireValidator(bankControl);      
            }
       
     });
     
     
     
    <!-- In component.html file-->
    
    
    <form [formGroup]="mainForm" (ngSubmit)="onFormSubmit()">
        <div>
          <label>
          <!-- You missed value attribute --> 
         <input type="radio" value="card" formControlName="cardOrBank">
           <span>Card</span>
       </label>
       <label>
         <input type="radio" value="bank" formControlName="cardOrBank">
           <span>Bank</span>
       </label>
        </div>
        <div formGroupName="cardDetails">
            <div>
                Card No: <input formControlName="cardNo">
            </div>
            <div>
                CVV: <input formControlName="cvv">
            </div>
        </div>
        <div formGroupName="bankDetails">
            <div>
                ACC No: <input formControlName="accNo">
            </div>
            <div>
                IFSC: <input formControlName="ifsc">
            </div>
        </div>
        <div>
            <button type="submit" [disabled]="!mainForm.valid">Submit</button>
        </div>
    </form>

    Here is the Working Example of your requirement :

    Working demo