How to dynamically add FormControl to FormArray on button click in Angular?
22,926
This example dynamically adds email fields to a reactive form. This would be used to enable users to add multiple email addresses (e.g. Home and Work).
This demo has the following dependencies: Angular 8, Angular Material, Bootstrap 4
End Result (Stackblitz Demo)
Step 1: Define the form model
constructor(private formBuilder: FormBuilder) { }
ngOnInit() {
this.emailForm = this.formBuilder.group({
emails: this.formBuilder.array([this.createEmailFormGroup()])
});
}
Step 2: Define a method to dynamically construct new FormGroup
private createEmailFormGroup(): FormGroup {
return new FormGroup({
'emailAddress': new FormControl('', Validators.email),
'emailLabel': new FormControl('')
})
}
Step 3: Define a method to dynamically add new FormGroup
to the FormArray
public addEmailFormGroup() {
const emails = this.emailForm.get('emails') as FormArray
emails.push(this.createEmailFormGroup())
}
Step 4 (Optional): Define method to delete FormGroup
public removeOrClearEmail(i: number) {
const emails = this.emailForm.get('emails') as FormArray
if (emails.length > 1) {
emails.removeAt(i)
} else {
emails.reset()
}
}
Step 5: Create the HTML form template
<form [formGroup]="emailForm">
<div formArrayName="emails">
<div class="row" *ngFor="let email of emailForm.get('emails').controls; let i = index"
[formGroupName]="i">
Note that within the formArrayName
element, the dynamic email FormGroups
are named based on the array index.
Final Form
<mat-toolbar color="primary">
Angular Form Demo - Dynamically add form controls
</mat-toolbar>
<form class="basic-container" [formGroup]="emailForm">
<div formArrayName="emails">
<div class="row" *ngFor="let email of emailForm.get('emails').controls; let i = index"
[formGroupName]="i">
<div class="col-1">
<mat-icon class="mt-3">email</mat-icon>
</div>
<mat-form-field class="col-4">
<input matInput formControlName="emailAddress" placeholder="Email" autocomplete="email">
<mat-error *ngFor="let validation of validationMsgs.emailAddress">
<div *ngIf="email.get('emailAddress').hasError(validation.type)">
{{validation.message}}
</div>
</mat-error>
</mat-form-field>
<mat-form-field class="col-4">
<mat-label>Label</mat-label>
<mat-select formControlName="emailLabel">
<mat-option *ngFor="let label of emailLabels" [value]="label">
{{label}}
</mat-option>
</mat-select>
</mat-form-field>
<div class="col-3">
<button class="float-left" mat-icon-button color="primary" aria-label="Remove/clear"
(click)="removeOrClearEmail(i)" matTooltip="Remove">
<mat-icon>highlight_off</mat-icon>
</button>
<button class="float-left" mat-icon-button color="primary" aria-label="Add"
(click)="addEmailFormGroup()" matTooltip="Add">
<mat-icon>add_circle_outline</mat-icon>
</button>
</div>
</div>
</div>
</form>
Final Component
import {Component} from '@angular/core';
import {FormBuilder, FormArray, FormControl, FormGroup, Validators} from '@angular/forms';
@Component({
selector: 'form-app',
templateUrl: 'app.component.html'
})
export class AppComponent {
public emailForm: FormGroup;
public emailLabels = ['Home', 'Work', 'Other'];
public validationMsgs = {
'emailAddress': [{ type: 'email', message: 'Enter a valid email' }]
}
constructor(private formBuilder: FormBuilder) { }
ngOnInit() {
this.emailForm = this.formBuilder.group({
emails: this.formBuilder.array([this.createEmailFormGroup()])
});
}
public addEmailFormGroup() {
const emails = this.emailForm.get('emails') as FormArray
emails.push(this.createEmailFormGroup())
}
public removeOrClearEmail(i: number) {
const emails = this.emailForm.get('emails') as FormArray
if (emails.length > 1) {
emails.removeAt(i)
} else {
emails.reset()
}
}
private createEmailFormGroup(): FormGroup {
return new FormGroup({
'emailAddress': new FormControl('', Validators.email),
'emailLabel': new FormControl('')
})
}
}
Author by
dilip t
Updated on July 09, 2022Comments
-
dilip t almost 2 years
How can I add a
formcontrol(option)
dynamically informarray
? I want to dynamically add questions to aformarray
. Upon clicking a button, it should update the display. I'm using angular 7.Component code
ngOnInit() { this.quizForm = this.fb.group({ questions: this.fb.array([]), questions2: this.fb.array([]), }); } //creating formcontrol createItem(): FormGroup { return this.fb.group({ ques: '', }); } //pushing code genField() { this.message = true; this.questions = this.quizForm.get('questions') as FormArray; this.questions.push(this.createItem()); }
HTML Template
I want to add form control option dynamically on button click and form control should be inside the
formArrayName="questions"
.<form [formGroup]="quizForm" class="adjust-form"> <div formArrayName="questions" *ngFor="let item of quizForm.get('questions').controls; let i = index;"> <div class="col-md-10 col-sm-6 mt-3 mb-3" [formGroupName]="i"> <label>{{i +1}} - {{question}} </label> <i class="flaticon-delete" (click)="quizForm.get('questions').controls.splice(i,1) " style="font-size: 9px;padding-left: 80px;"> </i> <div class="row"> <input type="text" class="form-control col-10" [(ngModel)]="item.ques" formControlName="ques" placeholder="Enter your question" required> <button *ngIf="i == 0" (click)="genField()" type="button" class="btn btn-secondary btn-elevate btn-circle btn-icon ml-4"> <i class="flaticon2-plus"></i> </button> </div> <div *ngIf="item.touched && item.invalid" class="kt-font-danger text-left"> <p>required</p> </div> </div> </div> </form>