FormGroup:
A FormGroup aggregates the values of each child FormControl into one object, with each control name as the key.
From: Anton Moiseev Book “Angular Development with Typescript, Second Edition.” :
When you need to programmatically add (or remove) controls to a form, use FormArray. It’s similar to FormGroup but has a length variable. Whereas FormGroup represents an entire form or a fixed subset of a form’s fields, FormArray usually represents a collection of form controls that can grow or shrink.
For example, you could use FormArray to allow users to enter an arbitrary number of emails.
From angular documentation you can see that
FormArray is an alternative to FormGroup for managing any number of unnamed controls. As with form group instances, you can dynamically insert and remove controls from form array instances, and the form array instance value and validation status is calculated from its child controls. However, you don't need to define a key for each control by name, so this is a great option if you don't know the number of child values in advance.
Let me show you their example and try to explain how I understand this. You can see source here
Imagine a form witch has following fields
profileForm = this.fb.group({
firstName: ['', Validators.required],
lastName: [''],
address: this.fb.group({
street: [''],
city: [''],
state: [''],
zip: ['']
}),
aliases: this.fb.array([
this.fb.control('')
])
});
Here we have firstName
, lastName
, address
and aliases
All field together are form group so we wrap everything in group
. At the same time address
is like a subgroup so we wrap it in another group
(You can look at template for better understanding)! Every form control here hes key
except aliases
and it means that you can push in it values as much as you want like simple array using formBuilder
methods like push
.
This is how I understand it, hope it helps someone.
FormArray is a variant of FormGroup. The key difference is that its data gets serialized as an array (as opposed to being serialized as an object in case of FormGroup). This might be especially useful when you don’t know how many controls will be present within the group, like dynamic forms.
Let me try to explain by a quick example. Say, you have a form where you capture a customer's order for Pizza. And you place a button to let them add and remove any special requests. Here is the component's html part:
<section>
<p>Any special requests?</p>
<ul formArrayName="specialRequests">
<li *ngFor="let item of orderForm.controls.specialRequests.controls; let i = index">
<input type="text" formControlName="{{i}}">
<button type="button" title="Remove Request" (click)="onRemoveSpecialRequest(i)">Remove</button>
</li>
</ul>
<button type="button" (click)="onAddSpecialRequest()">
Add a Request
</button>
</section>
and here is the component class defining and handling special requests:
constructor () {
this.orderForm = new FormGroup({
firstName: new FormControl('Nancy', Validators.minLength(2)),
lastName: new FormControl('Drew'),
specialRequests: new FormArray([
new FormControl(null)
])
});
}
onSubmitForm () {
console.log(this.orderForm.value);
}
onAddSpecialRequest () {
this.orderForm.controls
.specialRequests.push(new FormControl(null));
}
onRemoveSpecialRequest (index) {
this.orderForm.controls['specialRequests'].removeAt(index);
}
FormArray offers more flexibility than FormGroup in the sense that it is easier to manipulate FormControls using "push", "insert" and "removeAt" than using FormGroup's "addControl", "removeControl", "setValue" etc. FormArray methods ensure the controls are properly tracked in the form's hierarchy.
hope this helps.
In order to create a reactive forms, a parent FormGroup
is a must. This FormGroup
can further contain formControls
, child formGroups
or formArray
FormArray
can further contain array of formControls
or a formGroup
itself.
When should we use formArray?
Please read this beautiful post which explains the usage of formArray
The interesting example in that blog is about the trips formGroup
The structure of trips formGroup
using formControl
and formArray
would look something like:
this.tripForm = this.fb.group({
name: [name, Validators.required],
cities: new FormArray(
[0] ---> new FormGroup({
name: new FormControl('', Validators.required),
places: new FormArray(
[0]--> new FormGroup({
name: new FormControl('', Validators.required),
}),
[1]--> new FormGroup({
name: new FormControl('', Validators.required),
})
)
}),
[1] ---> new FormGroup({
name: new FormControl('', Validators.required),
places: new FormArray(
[0]--> new FormGroup({
name: new FormControl('', Validators.required),
}),
[1]--> new FormGroup({
name: new FormControl('', Validators.required),
})
)
}))
})
Do not forget to play with this DEMO, and notice the usage of array for cities
and places
of a trip.