Suggested Videos
Part 18 - Angular reactive forms cross field validation | Text | Slides
Part 19 - Angular formarray example | Text | Slides
Part 20 - Creating formarray of formgroup objects in Angular | Text | Slides
In this video, 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).
This is continuation to our previous video, Part 20. Please watch Part 20 from Angular 6 tutorial before proceeding.
Step 1 : Include Add Skill button
Place the following HTML inside the <div> element with class well. Notice the click event is bound to addSkillButtonClick() method. We will create this method in the component class next.
Part 18 - Angular reactive forms cross field validation | Text | Slides
Part 19 - Angular formarray example | Text | Slides
Part 20 - Creating formarray of formgroup objects in Angular | Text | Slides
In this video, 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).
This is continuation to our previous video, Part 20. Please watch Part 20 from Angular 6 tutorial before proceeding.
Step 1 : Include Add Skill button
Place the following HTML inside the <div> element with class well. Notice the click event 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 skills FormArray. 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 videos.
Hello sir ,
ReplyDeletePlease help me sir,I have a problem, i have written web api for fetching employee information from sql server. I am getting correct result for calling api to get employees or employee by ID. but when i call POST or PUT it gives me error -----
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://localhost:54074/api/values/?id=1. (Reason: CORS preflight channel did not succeed).[Learn More]
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://localhost:54074/api/values/?id=1. (Reason: CORS request did not succeed).
I have added required configuration (that u have told in some api videos for cross origine) in web config file
Please help me.
Thank you,
Umakant Jadhav
Please use the CORS extension for time being.You can find the CORS extension in google chrome extensions.It's related to cross origin problem not issue with your code.
ReplyDeleteI tried using square bracket for formGroupName in div tag, but getting error as FormGroupName is not a property of div
ReplyDeletedeploy a production build
ReplyDeleteERROR in src\app\employee\create-employee.component.html(81,37): : Property 'controls' does not exist on type 'AbstractControl'.
error : when deploy a production build : ng build --prod --base-href /empang/
ReplyDeleteERROR in src\app\employee\create-employee.component.html(81,37): : Property 'controls' does not exist on type 'AbstractControl'.
81. formArrayName="skills" *ngFor="let skill of employeeForm.get('skills').controls; let i = index">
formGroup['controls'].skills['controls']
DeleteMe too :(
ReplyDeleteProperty 'controls' does not exist on type 'AbstractControl'
use formGroup.get('commissionDetails')['controls']
Deleteinstead of formGroup.get('commissionDetails').controls
Found the solution!
ReplyDeleteCreate a get method in the ts and return as a FormArray.
then do xyz.controls in the html.
use this employeeForm.get('skills').value it worked for me
ReplyDelete