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

AngularTypescriptAngular2 FormsAngular4 Forms

Angular Problem Overview


I am trying a nested reactive form in Angular 4. It is working fine but when I try to build AOT it's throwing the error

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

I googled and tried few things but no luck. Could anyone tell me how to fix this issue?

<div [formGroup]="myForm">
    <div formArrayName="addresses">
        <div *ngFor="let address of myForm.get('addresses').controls; let i=index" 
                    class="panel panel-default">
            <span *ngIf="myForm.get('addresses').length > 1"
                    (click)="removeAddress(i)">Remove</span>
            <div [formGroupName]="i">
                <mat-form-field>
                    <input matInput formControlName="city" placeholder="city" value="">
                </mat-form-field>
            </div>

        </div>
    </div>
    <a (click)="addAddress()" style="cursor: default"> Add +</a>
</div>

typescript code below

constructor(private _fb: FormBuilder) {     
}

ngOnInit() {
    this.myForm = this._fb.group({
        addresses: this._fb.array([
            this.initAddress(),
        ])
    });
}
initAddress() {
    return this._fb.group({
        city: ['']
    });
}
addAddress() {
    const control = <FormArray>this.myForm.get('addresses');
    control.push(this.initAddress());
}
removeAddress(i: number) {
    const control = <FormArray>this.myForm.get('addresses');
    control.removeAt(i);
}

Angular Solutions


Solution 1 - Angular

Based on @Günter Zöchbauer comments , first i changed

myForm.controls['addresses'] to myForm.get('addresses') in both html and typescript

and then based on @yuruzi comment

changed myForm.get('addresses').controls to myForm.get('addresses')['controls']

Its working fine now. Thanks @gunter & yuruzi

Solution 2 - Angular

You can fix it easily though. Outsource the "get the controls" logic into a method of your component code (the .ts file):

getControls() {
  return (this.recipeForm.get('controlName') as FormArray).controls;
}

In the template, you can then use:

*ngFor="let ingredientCtrl of getControls(); let i = index"

This adjustment is required due to the way TS works and Angular parses your templates (it doesn't understand TS there).

Solution 3 - Angular

As an update to @sunny kashyap solution, I would write it this way:

getControls() {
  return (this.recipeForm.get('controlName') as FormArray).controls;
}

Solution 4 - Angular

Change myForm.get('addresses').controls to myForm.get('addresses').value will also fix the issue.

Solution 5 - Angular

for validation errors use...

<span *ngIf="f.YOUR_FORM_KEY.controls.YOUR_FORM_KEY.errors?.YOUR_FORM_VALIDATION">YOUR_FORM_KEY is YOUR_FORM_VALIDATION</span>

eg.

<span *ngIf="f.name.controls.name.errors?.required">Name is required</span>

ts file

get f(): any {
    return this.userForm.controls;
}

Solution 6 - Angular

to get the length of a FormArray , use simply length :

<span *ngIf="myForm.controls['addresses'].length > 1" (click)="removeAddress(i)">Remove</span>

Hope it helps

Solution 7 - Angular

Can use a custom interface

// Define AbstractFormGroup
export interface AbstractFormGroup extends FormGroup {
  controls: {
    [key: string]: AbstractFormGroup & AbstractFormGroup[] & AbstractControl & FormGroup & FormArray,
  }
}

// Usage example
class ... {
  myForm: AbstractFormGroup
  ...
  this.myForm = this.fb.group({...}) as AbstractFormGroup
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionMunna BabuView Question on Stackoverflow
Solution 1 - AngularMunna BabuView Answer on Stackoverflow
Solution 2 - Angularsunny kashyapView Answer on Stackoverflow
Solution 3 - AngularMotasem HalawaniView Answer on Stackoverflow
Solution 4 - AngularAdvait BaxiView Answer on Stackoverflow
Solution 5 - AngularMhar DanielView Answer on Stackoverflow
Solution 6 - AngularMohamed Ali RACHIDView Answer on Stackoverflow
Solution 7 - AngularUriy MerkUriyView Answer on Stackoverflow