Angular FormArray: Cannot find control with path [duplicate]
Asked Answered
U

2

15

I trying to build an Angular Reactive form where an account can add many students.

The form seems to work. When you hit Add Student it creates a new student but you check the console it says

ERROR Error: Cannot find control with path: 'studentsArray -> 1 -> firstName

and so on for each control in the array.

app.component.html

<form [formGroup]="accountForm">
<div>
    <input formControlName="firstName" placeholder="First name">
</div>
<div>
    <input formControlName="lastName" placeholder="Last name">
</div>
<div>
    <input formControlName="phone" placeholder="Phone">
</div>
<div>
    <input formControlName="email" placeholder="Email">
</div>
<button (click)="addStudent()" *ngIf="!showStudentForm">Add Student</button>
<div formArrayName="studentsArray">
    <div *ngFor="let student of studentsArray.controls; let i = index" [formGroupName]="i">
        <input formControlName="firstName" placeholder="First Name">
        <input formControlName="lastName" placeholder="Last Name">
        <input formControlName="dob" placeholder="Date of Birth">
    </div>
</div>

app.component.ts

import { Component, Input, OnChanges } from '@angular/core';
import { FormGroup, FormControl, Validators, FormArray, FormBuilder } from '@angular/forms';

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.css' ]
})
export class AppComponent  {
 @Input() account: Account;
  accountForm: FormGroup;

  constructor(private fb: FormBuilder) {
    this.createForm();
  }

   createForm() {
    this.accountForm = this.fb.group({
      'firstName': '',
      'lastName': '',
      'email': '',
      'phone': '',
      'studentsArray': this.fb.array([])
    });
   }

   ngOnChanges() {
    this.rebuildForm();
  }

  rebuildForm() {
    this.accountForm.reset({
      firstName: this.account.firstName,
      lastName: this.account.lastName,
      email: this.account.email,
      phone: this.account.phone
    });
    this.setStudents(this.account.students);
  }

  get studentsArray(): FormArray {
    return this.accountForm.get('studentsArray') as FormArray;
  }

  setStudents(students: Student[]) {
    const studentFGs = students.map(student => this.fb.group(student));
    const studentFormArray = this.fb.array(studentFGs);
    this.accountForm.setControl('studentsArray', studentFormArray);
  }

  addStudent() {
    this.studentsArray.push(this.fb.group(new Student()));
  }
}

export class Account {
  public firstName: '';
  public lastName: '';
  public email: '';
  public phone: '';
  public students: Student[];
}

export class Student {
  firstName: '';
  lastName: '';
  dob: '';
}

https://stackblitz.com/edit/angular-rqvv3a

Any suggestion will be much appreciated.

Ufa answered 16/7, 2018 at 15:4 Comment(0)
B
17

Method 1: Code example In your Component:

  addStudent() {
    this.studentsArray.push(this.fb.group({
      firstName:new FormControl (""),
      lastName: new FormControl (""),
      dob: new FormControl ("")
    }))
  }

Method 2: Code example In your component:

import { Student } from './student.model'

 addStudent() {
    this.studentsArray.push(this.fb.group(new Student()));
  }

Create Student Model: file name: student.model.ts

file contents:

export class Student{
  constructor(
    public firstName:string,
    public lastName:string,
    public dob:string
  ){}
}

For either Method 1 or 2:

In your Html:

<div formArrayName="studentsArray" ">
    <div *ngFor="let student of studentsArray.controls; let i = index" formGroupName="{{i}}">
        <input formControlName="firstName" placeholder="First Name">
        <input formControlName="lastName" placeholder="Last Name">
        <input formControlName="dob" placeholder="Date of Birth">
    </div>
</div>

You can display the value of the form for easy testing like this:

{{accountForm.value | json}}
Break answered 16/7, 2018 at 15:18 Comment(4)
Thanks for the quick reply @Farasi78. That works! I was hoping to pass it a model instead of entering all the controls. Is there a way to do this?Ufa
If you want to do it that way, create Student as a model and import it - I tried it with the definition inline and it didn't seem to work. stackblitz.com/edit/angular-llkzlk. Check that out.Break
@Ty did you manage to make it work? If so, and this answer was correct please indicate as appropriate. ThanksBreak
You're welcome! The second method allows you to do it with the model rather than having to specify each control individually.Break
S
1

In my case using Angular 10 and after many tries and research, I finally found the error, I was using [formControlName] notation in the <input> element, and as soon as I removed the square brackets for simply formControlName it finally works, not sure why but I hope it could help

Scoutmaster answered 27/6, 2022 at 21:42 Comment(1)

© 2022 - 2024 — McMap. All rights reserved.