Saturday 2 February 2019

Angular dynamic forms tutorial

Angular dynamic forms tutorial


In this topic, we will discuss generating FormGroups and FormControls dynamically at runtime.  


Here is what we want to do. Every time we click "Add Skill" button we want to generate another set of skill related form controls (i.e Skill, Experience & Proficiency). 


angular dynamic forms tutorial


Step 1 : Include Add Skill button

Place the following HTML inside the <div> element with class well. Notice the clickevent is bound to addSkillButtonClick() method. We will create this method in the component class next.

<div class="form-group">
  <div class="col-md-offset-2 col-md-4">
    <button type="button" class="btn btn-primary" (click)="addSkillButtonClick()">
      Add Skill
    </button>
  </div>
</div>

Step 2 : Include addSkillButtonClick() method in the component class 
  • From the root FormGroup "employeeForm" get a reference to the skillsFormArray. Notice we have passed the name of the FormArray (skills) as a parameter to the get() method.
  • The get() method returns the FormArray as an AbstractControl. We know it's a FormArray so we are type casting it to FormArray.
  • We are then calling the push() method of the FormArray to push a new FormGroup into the FormArray
  • The push() method calls addSkillFormGroup() method which returns an instance of the FormGroup with the 3 skill related form controls (skill, experience & proficiency)

addSkillButtonClick(): void {
  (<FormArray>this.employeeForm.get('skills')).push(this.addSkillFormGroup());
}

Step 3 : Loop over "skills" FormArray to dynamically generate the HTML input elements. 
  • Notice we are using *ngFor structural directive to loop over the "skills"FormArray
  • For each FormGroup in the FormArray, the respective HTML input elements (skill, experience & proficiency) will be generated
  • We are also binding the formGroupName directive to the loop variable i
  • Since we are binding to a variable do not forget to use square brackets around [formGroupName] directive, otherwise you will get a run-time error - Cannot find control with path: 'skills -> i'
<div formArrayName="skills"
     *ngFor="let skill of employeeForm.get('skills').controls; let i = index">
  <div [formGroupName]="i">
      <!-- Skill Name Label & Form Control HTML
      Experience Label & Form Control HTML
      Proficiency Label & Form Control HTML -->
  </div>
</div>

At the moment there are several problems with the dynamically generated HTML input elements

  • The dynamically generated HTML input elements have the same id. For example, all the "skillName" textboxes have the same id "skillName". Not only the id, even the for attribute value of the labels is also the same.
  • As a result when we click on a label of an input element, the wrong textbox receives focus.
  • Also, the validation is broken.
  • We will discuss fixing these issues in our next upcoming topics.

No comments:

Post a Comment