Search code examples
angulartypescriptangular-reactive-formsangular-components

Toggle field in Angular Reactive form (form validation) based on a checkbox in a different component


I have a complex form which fields are based on toggling checkboxes in a different component (parent). I need to validate the form meaning that some fields might be disabled and some not. I need this to be dynamic and changes based on the ticking/unticking of the checkboxes, rather than have it working just for initialization. I have tried multiple examples with no luck..

parent.component.html

<input type="checkbox" id="check" ng-model="checked" (click)='toggleCheckform()'>
<label for="check">Check me</label>

<mat-tab label="child">
   <child [isCheck]="toggleCheck" (messageToEmit)="getMessage($event)"></child>
</mat-tab>

parent.component.ts

export class ParentComponent {

    constructor() { }

    toggleCheck: boolean = false;

    ngOnInit() {
    }

    toggleCheckform() {
        this.toggleCheck = !this.toggleCheck;
    }
}

child.component.ts

export class ChildComponent {

  @Input() isCheck: boolean;

  testForm = this.fb.group({
    Field1: ['', Validators.required],
    Field2: ['', Validators.required]
  });

  get Field1() { return this.testForm.get('Field1'); }
  get Field2() { return this.testForm.get('Field2'); }

  if(isCheck){
    this.testForm.get('Field1').disable();
  }

  onSubmit() {
    // TODO: Use EventEmitter with form value
    console.warn(this.testForm.value);
  }

  constructor(private fb: FormBuilder) {
  }

  ngOnInit() {
  }

child.component.html

    <form [formGroup]="testForm" (ngSubmit)="onSubmit()">

    <div *ngIf="isCheck">
        <div class="form-group">
           <label for="Field1">Field1</label>
                <input type="text" class="form-control" id="Field1" formControlName="Field1">
        </div>
    </div>

    <div class="form-group">
       <label for="Field2">Field2</label>
           <input type="text" class="form-control" id="Field2" formControlName="Field2">
    </div>

    </form>

So based on the checkbox on the parent component I want to be able to enable/disable that form field for validation. Tried a lot of approaches, the example works when the form is initialized but after it does not. Please help.


Solution

  • you need use a "setter" in the input

    _isCheck:boolean
    @Input() 
    set isCheck(value)
    {
      this._isCheck=true;
      const control=this.testForm.get('Field1')
      if(control)
      {
        if (value)
          control.enable();
        else
          control.disable();
       }
    }
    
    get isCheck()
    {
        return this._isCheck
    }
    

    NOTE: when you disabled a FormControl the form.value NOT include the value (you need use form.getRawValue()) futhermore, the form is valid whatever the value of the formControl disabled was

    A stackblitz