Search code examples
angularnested-formsangular-reactive-forms

Unable to setValidators(Validators.required) from parent component to child component


I have a form which consist of a checkbox and a component named address. So whenever user click the checkbox app should set the address to required field. This is my HTML.

<form [formGroup]="registerForm">
   <app-address-input formControlName="address"></app-address-input><br>
   <input type="checkbox" formControlName="check"> Check?
</form>
<p>Form value: {{ registerForm.value | json }}</p>
<p>Form status: {{ registerForm.status | json }}</p> 

This is my component

export class AppComponent implements OnChanges {
  registerForm = new FormGroup({
      address: new FormControl(undefined),
      check: new FormControl(undefined)
  });
  get address() {
      return this.registerForm.get('address')
  }
  get check() {
      return this.registerForm.get('check')
  }
  ngOnChanges() {
      this.registerForm.get('check').valueChanges.pipe(tap(val => {
      if(val){
            this.registerForm.get('address').setValidators(Validators.required)
       }
        this.registerForm.get('address').updateValueAndValidity();
      })).subscribe();
   }
}

Solution

  • You should subscribe to the valueChanges of the form control in ngOnInit instead of ngOnChanges

     ngOnInit() {
            this.registerForm.get('check').valueChanges.subscribe( (val) => {
               if(val){
                  console.log(val)
                     this.registerForm.get('address').setValidators(Validators.required)
                }
                this.registerForm.get('address').updateValueAndValidity();
                console.log(this.registerForm.valid);         
             });
     }
    

    Your component doesn't have any @Input(), so the ngOnChanges life cycle won't get invoked. so the subscribe of the form control can't work. You should subscribe the form control in ngOnInit, so that the valueChanges of the form control gets subscribed.

    Difference between these two life cycles explained in Angular Docs

    ngOnChanges

    Respond when Angular (re)sets data-bound input properties. The method receives >a SimpleChanges object of current and previous property values. Called before ngOnInit() and whenever one or more data-bound input properties >change.

    ngOnInit

    Initialize the directive/component after Angular first displays the data-bound >properties and sets the directive/component's input properties. Called once, after the first ngOnChanges().