Support us .Net Basics C# SQL ASP.NET Aarvi MVC Slides C# Programs Subscribe Download

Creating formarray of formgroup objects in Angular

Suggested Videos
Part 17 - How to make angular custom validator reusable | Text | Slides
Part 18 - Angular reactive forms cross field validation | Text | Slides
Part 19 - Angular formarray example | Text | Slides

In this video we will discuss Creating a FormArray of FormGroup objects


If you are wondering, why are we doing this?

Well, this is preparation for dynamically creating FormGroups at runtime. Every time we click, "Add Skill" button on the "Employee Form" below, we want to dynamically generate a new set of skill related form fields. So in this video, we will do all the preparation required for that.


angular formarray of formgroup

Component Class Code :

constructor(private fb: FormBuilder) { }

ngOnInit() {
  this.employeeForm = this.fb.group({
    fullName: ['', [Validators.required]],
    contactPreference: ['email'],
    // Other Form Controls..
    // Create skills FormArray using the injected FormBuilder
    // class array() method. At the moment, in the created
    // FormArray we only have one FormGroup instance that is
    // returned by addSkillFormGroup() method
    skills: this.fb.array([
      this.addSkillFormGroup()
    ])
  });

  // Rest of the code
}

addSkillFormGroup(): FormGroup {
  return this.fb.group({
    skillName: ['', Validators.required],
    experienceInYears: ['', Validators.required],
    proficiency: ['', Validators.required]
  });
}

In the template, use the formArrayName directive to bind to the skills FormArray. Now the important point to keep in mind is, in the component class, we only have one FormGroup instance in the skills FormArray. That one FormGroup instance is present at index position ZERO in the FormArray. This is the reason we have set formGroupName="0".

HTML in the view template

<div class="well">
  <div formArrayName="skills">
    <div formGroupName="0">
      <!-- Skill Name Label & Form Control HTML
        Experience Label & Form Control HTML
        Proficiency Label & Form Control HTML -->
    </div>
  </div>
</div>

With the above 2 changes, the validation is broken. To fix it, modify the code in logValidationErrors() method as shown below.

logValidationErrors(group: FormGroup = this.employeeForm): void {
  Object.keys(group.controls).forEach((key: string) => {
    const abstractControl = group.get(key);

    this.formErrors[key] = '';
    if (abstractControl && !abstractControl.valid &&
      (abstractControl.touched || abstractControl.dirty)) {
      const messages = this.validationMessages[key];

      for (const errorKey in abstractControl.errors) {
        if (errorKey) {
          this.formErrors[key] += messages[errorKey] + ' ';
        }
      }
    }

    if (abstractControl instanceof FormGroup) {
      this.logValidationErrors(abstractControl);
    }

    // We need this additional check to get to the FormGroup
    // in the FormArray and then recursively call this
    // logValidationErrors() method to fix the broken validation
    if (abstractControl instanceof FormArray) {
      for (const control of abstractControl.controls) {
        if (control instanceof FormGroup) {
          this.logValidationErrors(control);
        }
      }
    }
  });
}

Next video : We will discuss generating skill realted FormGroups and FormControls dynamically at runtime.

angular 6 tutorial for beginners

1 comment:

It would be great if you can help share these free resources