Saturday 2 February 2019

Creating formarray of formgroup objects in Angular

Creating formarray of formgroup objects in Angular


In this topic 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 topic: We will discuss generating skill realted FormGroups and FormControls dynamically at runtime. 

No comments:

Post a Comment