1

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?

6
  • When using ngIf, could you protect the code for cases where child is undefined? Commented Sep 4, 2018 at 18:53
  • @ConnorsFan, I'm not sure that I understand what you're asking. Can you rephrase? Commented Sep 4, 2018 at 18:56
  • You call the methods of the child from the parent, but it does not work when the child does not exist. Can you avoid calling the child methods in that case (when you see that child is not defined)? Commented Sep 4, 2018 at 19:00
  • @ConnorsFan, if I avoid calling the child method then the validators would still be active, would they not? Commented Sep 4, 2018 at 19:28
  • If the validators are defined in the child, and the child does not exist, I would assume that these validators don't exist. Disclaimer: I am not very familiar with reactive forms. Commented Sep 4, 2018 at 19:32

2 Answers 2

3

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

Sign up to request clarification or add additional context in comments.

Comments

2

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.