132

I am trying to iterate over a formArray in my component but I get the following error

Error: Cannot find control with unspecified name attribute

Here is what the logic looks like on my class file

export class AreasFormComponent implements OnInit {
    public initialState: any;
    public areasForm: FormGroup;

    constructor(private fb: FormBuilder) { }

    private area(): any {
      return this.fb.group({
          name: ['', [Validators.required]],
          latLong: ['', [Validators.required]],
          details: ['', [Validators.required]]
      });
    }

    public ngOnInit(): void {
        this.areasForm = this.fb.group({
            name: ['', [Validators.required]],
            areas: this.fb.array([this.area()])
        });
    }
}

and my template file

<form class="areas-form" [formGroup]="areasForm" (ngSubmit)="onSubmit(areasForm.values)">
    <md-input-container class="full-width">
        <input mdInput placeholder="Location Name" type="text" formControlName="name" required>
        <md-error *ngIf="areasForm.get('name').hasError('required')">Please enter the locationName</md-error>
    </md-input-container>
    <md-grid-list cols="1" [formArrayName]="areas">
        <md-grid-tile formGroupName="i"  colspan="1" rowHeight="62px" *ngFor="let area of areasForm.controls.areas.controls; let i = index ">
            <md-grid-list cols="3" rowHeight="60px">
                <md-grid-tile colspan="1">
                    <md-input-container class="full-width">
                        <input mdInput placeholder="Area Name" type="text" formControlName="name" required>
                        <md-error *ngIf="areasForm.get('areas').controls[i].name.hasError('required')">Please enter the area name</md-error>
                    </md-input-container>
                </md-grid-tile>
                <md-grid-tile colspan="1">
                    <md-input-container class="full-width">
                        <input mdInput placeholder="details" type="text" formControlName="details" required>
                        <md-error *ngIf="areasForm.get('areas').controls[i].name.hasError('required')">Please enter the locationName</md-error>
                    </md-input-container>
                </md-grid-tile>
                <md-grid-tile colspan="1">
                    <button md-fab (click)="remove(i)"><md-icon>subtract</md-icon>Remove Area</button>
                </md-grid-tile>
            </md-grid-list>
        </md-grid-tile>
    </md-grid-list>
    <button type="submit" [disabled]="areasForm.invalid" md-raised-button color="primary">Submit</button>
</form>

17 Answers 17

179

Remove the brackets from

[formArrayName]="areas" 

and use only

formArrayName="areas"

This, because with [ ] you are trying to bind a variable, which this is not. Also notice your submit, it should be:

(ngSubmit)="onSubmit(areasForm.value)"

instead of areasForm.values.

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

6 Comments

Is your plunkr broken?
and yet [FormGroup]="areasForm" is correct? Angular is really kicking me in the pants....
The curly brackets were the problem in my case with the formGroupName
@greg late to comment... [formGroup]="areasForm" is correct because areasForm is a variable in your component TS, whereas areas is not. It is property of the areasForm :)
I had this error pointing to row "106" in my template. It turned out that the formControl before that line was misspelled! So this error is saying that error is at row X, when it is actually before that. Oh btw, upgrade to 14+ if you can. It has typed forms!
|
27

In my case I solved the issue by putting the name of the formControl in double and sinlge quotes so that it is interpreted as a string:

[formControlName]="'familyName'"

similar to below:

formControlName="familyName"

1 Comment

Thank you for the explanation. I kept seeing the formControlName wrapped in single quotes but the difference between passing it as a string vs the formControl object didn't click until seeing this.
11

The problem for me was that I had

[formControlName]=""

Instead of

formControlName=""

1 Comment

I needed to change from [formControl] to formControlName
7

For me, I was trying to add [formGroupName]="i" and/or formControlName and forgetting to specify the parent formArrayName. Pay attention to your form group tree.

2 Comments

I was using both as well. Remember to put the formArrayName on a DOM-element higher up in the hierarchy than [formGroupName]="i" (e.g. on the loop element: <div *ngFor=let ctrl of formArrayCtrl; let i = index"><div [formGroupName]="i"></div></div>)
Pay attention to form group tree helped me.
7

Instead of

formGroupName="i"

You must use:

[formGroupName]="i"

Tips:

Since you're looping over the controls, you've already the variable area, so you can replace this:

*ngIf="areasForm.get('areas').controls[i].name.hasError('required')"

by:

*ngIf="area.hasError('required', 'name')"

1 Comment

Thanks, that seemed to be part of the problem but the answer above solved my issue.
4

This was happening for me because I had fromArrayName instead of formArrayName somewhere 😑

Comments

3

So, I had this code:

<div class="dropdown-select-wrapper" *ngIf="contentData">
    <button mat-stroked-button [disableRipple]="true" class="mat-button" (click)="openSelect()" [ngClass]="{'only-icon': !contentData?.buttonText?.length}">
      <i *ngIf="contentData.iconClassInfo" class="dropdown-icon {{contentData.iconClassInfo.name}}"></i>
      <span class="button-text" *ngIf="contentData.buttonText">{{contentData.buttonText}}</span>
    </button>
    <mat-select class="small-dropdown-select" [formControl]="theFormControl" #buttonSelect (selectionChange)="onSelect(buttonSelect.selected)" (click)="$event.stopPropagation();">
      <mat-option *ngFor="let option of options" [ngClass]="{'selected-option': buttonSelect.selected?.value === option[contentData.optionsStructure.valName]}" [disabled]="buttonSelect.selected?.value === option[contentData.optionsStructure.valName] && contentData.optionSelectedWillDisable" [value]="option[contentData.optionsStructure.valName]">
        {{option[contentData.optionsStructure.keyName]}}
      </mat-option>
    </mat-select>
  </div>

Here I was using standalone formControl, and I was getting the error we are talking about, which made no sense for me, since I wasn't working with formgroups or formarrays... it only disappeared when I added the *ngIf to the select it self, so is not being used before it actually exists. That's what solved the issue in my case.

<mat-select class="small-dropdown-select" [formControl]="theFormControl" #buttonSelect (selectionChange)="onSelect(buttonSelect.selected)" (click)="$event.stopPropagation();" *ngIf="theFormControl">
          <mat-option *ngFor="let option of options" [ngClass]="{'selected-option': buttonSelect.selected?.value === option[contentData.optionsStructure.valName]}" [disabled]="buttonSelect.selected?.value === option[contentData.optionsStructure.valName] && contentData.optionSelectedWillDisable" [value]="option[contentData.optionsStructure.valName]">
            {{option[contentData.optionsStructure.keyName]}}
          </mat-option>
        </mat-select>

1 Comment

I had the problem when a host modal component was dismissed. I had to use ngIf to check whether the control was still available when closing my dialog.
1

For me, the issue was I was missing the field name in the form builder:

  return this.fb.group({
      name: ['', [Validators.required]],
      latLong: ['', [Validators.required]],
      details: ['', [Validators.required]],
      // missing field name!
  });

Comments

1

In my case, I forgot to initialize the form in ngOnInit() when using [formControl]="customForm".

Comments

1

In Angular 17, I encountered an issue where the initialization was delayed, causing the [formControl] to temporarily bind to null. To address this, I used *ngIf='!!employerForm' to ensure that the employerForm was initialized before rendering the template. This approach prevented the form from displaying with uninitialized controls.

    <input  
          *ngIf='!!employerForm'
          type="text"
          [formControl]="employerForm?.get('role_title')"
          [attr.data-test-id]="'application_detail_job_title_txt'" />

Comments

0

This happened to me because I left a formControlName empty (formControlName=""). Since I didn't need that extra form control, I deleted it and the error was resolved.

Comments

0

Only WinMerge made me find it (by comparison with a version that works). I had a case problem on formGroupName. Brackets around this word can lead to the same problem.

Comments

0

I had accidentally entered the control name when creating the formGroup:

getFormGroup(dataItem: any): FormGroup {
    return new FormGroup({
        'Id': new FormControl(dataItem != null ? dataItem.Id : ''),
        'PsDepartmentId': new FormControl(dataItem != null ? dataItem.DepartmentId : '', Validators.required), //Accidentally used 'DepartmentId' on this line
        'IsActive': new FormControl(dataItem != null ? dataItem.IsActive : true)
    });
}

Then it failed in the html when I did

          <kendo-dropdownlist id="ps-dpts-dropdown" [data]="psDepartments" textField="ConCatedName" valueField="Id"
          [formControl]="formGroup.get('DepartmentId')" [valuePrimitive]="true">                  
          </kendo-dropdownlist>

Comments

0

Angular 13! formControlName should not empty.

formControlName=""

Comments

0

It was because formControlName='' was empty.

Comments

0

Change [formControl] to formControlName and simple give the name. formControlName="name". Main thing to notice it should be under proper formGroupName or formArrayName.

Comments

0

For me, I declared a input name with formControl which should be avoided.

Renaming the formControl to another name like formCtrl removed the error

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.