Angular FormArray is a class in Angular that represents an array of FormControl, FormGroup, or FormArray instances.
It provides a way to manage and validate multiple form controls dynamically.
To create dynamic nested form in Angular we will use FormArray. You have to import it from the @angular/forms module.
If you are new to Reactive Forms, please refer to Full Angular Reactive Forms & Form Validation Tutorial.
Step by step Explanation
Set up Angular Project
Install the Angular CLI with below command.
npm install @angular/cli -g
Now, you have to install the brand new Angular project using below command.
ng new angular-demo
Angular CLI asks for your choices while setting up the project…
Would you like to add Angular routing?
Select y and Hit Enter.
Which stylesheet format would you like to use? (Use arrow keys)
Choose SCSS and hit Enter
Use command to navigate into the project directory:
cd angular-demo
Remove Angular TypeScript Errors
To get rid from the errors:
Property ‘xxxName’ comes from an index signature, so it must be accessed with [‘xxxName’]
This setting makes sure profound consistency between accessing a field via the “dot” (obj.key)
syntax, and “indexed” (obj["key"])
and the way which the property is declared in the type.
Without this flag, TypeScript will allow you to use the dot syntax to access fields which are not defined:
Make sure to set following properties to false in tsconfig.json file:
"compilerOptions": {
...
...
"strict": false,
"noPropertyAccessFromIndexSignature": false,
...
...
},
"angularCompilerOptions": {
"strictTemplates": false
}
Understand Nested Forms in Angular
Let’s assume if a user requires to add an item using the form. In this kind of condition, you have to create a form which allows a user to add dynamic form fields to add additional data.
Setting Up Reactive Form
Importing ReactiveFormsModule API
To work with Reactive Forms in Angular, please import ReactiveFormsModule
service in app.module.ts
file.
import { ReactiveFormsModule } from '@angular/forms';
@NgModule({
imports: [
ReactiveFormsModule
],
})
export class AppModule { }
Understand Basic Reactive Forms Services
Reactive forms are used to manage complex data entered by the user in the form. Let’s focus on some of the useful services of Reactive Forms.
AbstractControl
: This is the main class for controlling the behavior and properties of, FormGroup, FormControl, and FormArray.
FormBuilder
: It provides helpful methods to create control instances in Angular 7 Reactive Forms.
FormGroup
: FormGroup is a top-level API which maintains the values, properties and validation state of a group of AbstractControl instance in Angular.
FormControl
: It communicates with an HTML Form element like input or select tag, this api handles the individual form value and validation state.
FormArray
: FormArray API maintains the values, properties and validation state of an array of the AbstractControl instances.
ngSubmit
: This event is called when the form is submitted.
Setting Up Reactive Form in Angular Component HTML Template
app.component.html
<!-- Form starts -->
<form [formGroup]="registrationForm" (ngSubmit)="onSubmit()">
<button type="submit" class="btn btn-danger btn-lg btn-block">Submit Form</button>
</form><!-- Form ends -->
Setting Up Reactive Form
app.component.ts
import { Component } from '@angular/core';
import { FormBuilder, FormArray } from "@angular/forms";
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
})
export class AppComponent {
constructor(public fb: FormBuilder) {}
/*############ Registration Form ############*/
registrationForm = this.fb.group({
addDynamicElement: this.fb.array([])
})
// Submit Registration Form
onSubmit() {
alert(JSON.stringify(this.registrationForm.value))
}
}
Setting Up Nested Form Layout Using HTML & FormArrayName Directive
Let’s set up the HTML layout for creating Nested forms group in Angular. I will be using following directives to work with nested forms in Angular.
formArrayName
: It syncs a nested FormArray to a DOM element.
*ngFor
: It’s a structural directive provided by Angular that loops over every item in a collection.
<div class="jumbotron text-center">
<h2 class="display-5">
Angular 16 Nested Form Example
</h2>
</div>
<div class="container">
<div class="row custom-wrapper">
<div class="col-md-12">
<!-- Form starts -->
<form [formGroup]="registrationForm" (ngSubmit)="onSubmit()">
<!-- Add items dynamically-->
<div class="group-gap" formArrayName="addDynamicElement">
<h5 class="mb-3">Add Products</h5>
<div class="mb-3">
<button type="button" class="btn btn-sm btn-success mb-3 btn-block" (click)="addItems()">Add Items</button>
<ul class="subjectList">
<li *ngFor="let item of addDynamicElement.controls; let i = index">
<input type="text" class="form-control" [formControlName]="i">
</li>
</ul>
</div>
<!-- Submit Button -->
<button type="submit" class="btn btn-danger btn-lg btn-block">Submit Form</button>
</div>
</form><!-- Form ends -->
</div>
</div>
</div>
Understand Dynamic Forms Array
I will add a JavaScript getter method to access the addDynamicElement
form control. Then i will assign FormArray
to form control, it will make it an array.
Once we are done with this process, then i will addItems() function and push the dynamically created form control into the addDynamicElement array.
/*############### Add Dynamic Elements ###############*/
get addDynamicElement() {
return this.registrationForm.get('addDynamicElement') as FormArray
}
addItems() {
this.addDynamicElement.push(this.fb.control(''))
}
Let’s checkout the output.
app.component.ts
import { Component } from '@angular/core';
import { FormBuilder, FormArray, Validators } from '@angular/forms';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss'],
})
export class AppComponent {
constructor(public fb: FormBuilder) {}
/*################ Registration Form ################*/
registrationForm = this.fb.group({
addDynamicElement: this.fb.array([]),
});
/*############### Add Dynamic Elements ###############*/
get addDynamicElement() {
return this.registrationForm.get('addDynamicElement') as FormArray;
}
addItems() {
this.addDynamicElement.push(this.fb.control(''));
}
// Submit Registration Form
onSubmit() {
alert(JSON.stringify(this.registrationForm.value));
}
}
Angular Nested Form Demo
We’ve created nested form with Angular, we have used reactive forms to manage nested data required by the user.
The following command will start a development server, compile and run your app.
ng serve --open
Let’s check out below how does it work?
Conclusion
A dynamic nested form is a very useful form component. A dynamic web form is a type of form that allows users to dynamically add or remove nested form fields on the go.
It comes to handy when you require to collect repeating data from the users without having the knowledge the exact number of entries beforehand.