When to use FormGroup vs. FormArray?

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.


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.