Accessing Nested Controls of Angular Forms

Viewed 96

I'm upgrading an application from Angular 2 to 7, and it looks like most of my forms have broken. I have multiple instances where I receive the following error:

Property 'controls' does not exist on type 'AbstractControl'

In this particular instance, I have a block that appears to looping through and validating form arrays.

for (let i = 0, len = this.form.controls[control].controls.length; i < len; i++) {

  this.form.controls[control].controls[i].controls.ConditionTypeId.setValidators(Validators.required);
  this.form.controls[control].controls[i].controls.ConditionTypeId.updateValueAndValidity();
  this.form.controls[control].controls[i].controls.ToBeCompletedDate.setValidators(Validators.required);
  this.form.controls[control].controls[i].controls.ToBeCompletedDate.updateValueAndValidity();
}

Has there been a major change in how nested forms/form arrays work since Angular 2, and if so, what would be the most efficient way for me to refactor any code that deals with nested forms in this manner?

1 Answers

I'm not sure when the change occurred because I didn't get serious with Angular until v4. But I believe your issue is just a bit stricter typing or restructuring of the form classes. AbstractControl is a generic abstract class for these form classes. The FormArray class extends that and adds that controls property that you're looking for. But FormGroup.controls[...] just returns the generic AbstractControl. So, you have to cast it to a FormArray before trying to get the controls from it:

(this.form.controls[control] as FormArray).controls[i].controls...

The more common pattern is to create a getter for the specific arrays, but a simple function in the backing ts file might be more appropriate in your case:

getFormArray(controlName) {
  return this.myForm.get(controlName) as FormArray;
}
Related