Reputation: 31055
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
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
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