adam0101
adam0101

Reputation: 31055

Using reactive forms, how to disable validation on nested angular components when hidden?

I have a parent component that includes multiple nested child components. The child components can be conditionally shown or hidden so I need to be able to enable and disable the validators in those child components so that when a child is hidden, its validators don't make the form invalid.

I tried adding public methods on the child components like this:

clearValidators() {
  this.formControl.clearValidators();
}

resetValidators() {
  this.formControl.setValidators(Validators.compose([
    Validators.required,
    CustomValidators.existsIn(this.items.map(l => l[this.itemIdField]))
  ]));
}

And then I call those methods from the parent by getting a reference to the child using @ViewChild(ChildComponent) child: ChildComponent;, but this doesn't work if I use *ngIf to hide the child, because the @ViewChild reference becomes undefined.

I tried changing from *ngIf to [hidden], but that throws the error

Cannot find control with path: 'parent-> child'

I'm not sure why. What is the correct way to handle validators in nested components?

Upvotes: 1

Views: 13639

Answers (2)

adam0101
adam0101

Reputation: 31055

I couldn't find a clean way to get a reference to the child that wouldn't break by using *ngIf and I didn't want to clear and set validators directly from the parent because it seems to break encapsulation to require the parent to have explicit knowledge of what validators the child component requires.

I ended up using this.childFormControl.disable() and this.childFormControl.enable() which allows me to disable the validators for the control and it automatically does all child controls within it.

Update

I just found this comment from someone on the Angular team that might be useful. They suggest adding and removing the form controls like this.form.removeControl('name') and then write the *ngIf so that the DOM depends on the existence of the control as in *ngIf="form.contains('name')". This might be a better way to go.

Upvotes: 2

Paola Reyes
Paola Reyes

Reputation: 162

I needed something similar in the past and i did the following:

this.formName.controls.formControlParentName.valueChanges.subscribe(val => {
  if(val){
    this.formName.controls.formControlChildName.setValidators([Validators.required]);
  } else {
    this.formName.controls.formControlChildName.clearValidators();
    this.formName.controls.formControlChildNames.updateValueAndValidity();
  }
});

in this particular case, I had a checkbox and if the user clicks on it, appears a new text-area with a nested form-control

Upvotes: 3

Related Questions