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

112,596

Solution 1

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

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

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

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

Solution 4

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

Solution 5

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;
}
Share:
112,596

Related videos on Youtube

Munna Babu
Author by

Munna Babu

JavaScript Developer

Updated on November 22, 2020

Comments

  • Munna Babu
    Munna Babu over 3 years

    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);
    }
    
    • Günter Zöchbauer
      Günter Zöchbauer over 6 years
      I think the preferred way is myForm.get('addresses')
    • Munna Babu
      Munna Babu over 6 years
      @GünterZöchbauer do we need to use this in HTML ngFor or in the Typescript ?
    • Günter Zöchbauer
      Günter Zöchbauer over 6 years
      Should work in both if myForm is an AbstractControl
    • Munna Babu
      Munna Babu over 6 years
      @GünterZöchbauer updated code in the question as per ur suggestion, its working fine but AOT throw same error :( any idea ? pls chk code
    • Günter Zöchbauer
      Günter Zöchbauer over 6 years
      Then you probably changed it on the wrong place. It's quite unlikely that get() throws an error that controls() doesn't exist.
    • yurzui
      yurzui over 6 years
      create getter like get addressesControls() { return (<FormArray>this.myForm.get('addresses')).controls; } or just use the following myForm.get('addresses')['controls']
    • Munna Babu
      Munna Babu over 6 years
      @yurzui Thanks just update myForm.get('addresses')['controls'] in HTML , its working fine now
    • HD..
      HD.. over 6 years
      how this thing will itterate may I know Munna rentalPricingForm.controls.pricingBundle.controls[i].control‌​s.packageName.errors
  • Munna Babu
    Munna Babu over 6 years
    Thanks. But It doesn't fix issue.
  • Munna Babu
    Munna Babu over 6 years
    Yes @mohammed, pls chk the updated code in question
  • Mohamed Ali RACHID
    Mohamed Ali RACHID over 6 years
    can you please try this let address of myForm.controls.addresses.controls instead of let address of myForm.get('addresses').controls
  • Victor Reyes
    Victor Reyes almost 5 years
    Maybe on later angular versions you have to use return (this.recipeForm.get('controlName') as FormArray).controls;
  • Rafael L R
    Rafael L R almost 5 years
    My case: form.get('user')['controls'].profile. its ok tnks
  • Kelvin Cayman
    Kelvin Cayman about 4 years
    This wrked for me seamlessly. Thanks Man! In the tempate myForm.get('addresses')['controls'] In the ts const control = this.myForm.controls.addresses as FormArray
  • Majesty
    Majesty over 3 years
    Kinda woodoo magic, it must be working without array notation....