angulartypescriptangular-reactive-formsformarrayangular-formbuilder

Showing items in Form Array


I need to show users' names and a list of their courses. Different users have different numbers of courses. Thus, I am trying Angular Form Array.

Here is my .ts:

this.form = this.fb.group({
  name: [''],
  courses: this.fb.array([
    this.fb.group({          
      name: [''],     
    })
  ]),
});

get courses() {
  return this.form.controls["courses"] as FormArray;
}

and my .html:

<form [formGroup]="form" (ngSubmit)="onSubmit()">
   <div class="mb-3">
     <label>Name</label>
     <input type="text" formControlName="name"/>                    
   </div>
   <div class="mb-3">
     <label>Courses</label>                    
     <div formArrayName="courses">
       <div *ngFor="let course of courses.controls; let i = index">
         <div [formGroupName]="i">
            <input type="text" formControlName="name"/>
         </div>                                                                                                       
       </div>
     </div>
   </div>      
</form>

The problem is that a user has two courses but only one of the courses is shown! Does anyone know what is the problem?

P.s. Happy new year :)


Solution

  • You have to ensure each course instance will require a FormGroup instance in the courses array.

    for (let course of this.data.courses) {
      let courseFormGroup = this.newCourseFromGroup();
      courseFormGroup.patchValue(course);
    
      this.courses.push(courseFormGroup);
    }
    

    To avoid code duplication in creating a Course FormGroup, suggest creating a function as below:

    newCourseFromGroup() {
      return this.fb.group({
        name: [''],
      });
    }
    

    Also, concerned that your current code will add a FormGroup instance into the courses FormArray. This will result an additional FormGroup instance would be added if you push the FormGroup as my proposed code.

    Thus, you should only initialize the FormArray by adding a default FormGroup for courses FormArray if the data doesn't exist as below:

    this.form = this.fb.group({
      name: [''],
      courses: this.fb.array([]),
    });
    
    if (this.data) {
      for (let course of this.data.courses) {
        let courseFormGroup = this.newCourseFromGroup();
        courseFormGroup.patchValue(course);
    
        this.courses.push(courseFormGroup);
      }
    } else {
      this.addCourse();
    }
    

    Demo @ StackBlitz