When to use FormGroup vs. FormArray?

AngularAngular2 FormsAngular Reactive-Forms

Angular Problem Overview


FormGroup:

> A FormGroup aggregates the values of each child FormControl into one > object, with each control name as the key.

const form = new FormGroup({ first: new FormControl('Nancy', Validators.minLength(2)), last: new FormControl('Drew') });

FormArray:

> A FormArray aggregates the values of each child FormControl into an > array.

const arr = new FormArray([
  new FormControl('Nancy', Validators.minLength(2)),
  new FormControl('Drew')
]);

When should one be used over the other?

Angular Solutions


Solution 1 - Angular

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.

Solution 2 - Angular

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.

Solution 3 - Angular

From: Anton Moiseev's 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.

Solution 4 - Angular

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.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionjcrollView Question on Stackoverflow
Solution 1 - AngularUsmanView Answer on Stackoverflow
Solution 2 - AngularAmit ChigadaniView Answer on Stackoverflow
Solution 3 - AngularH S ProgrView Answer on Stackoverflow
Solution 4 - AngularGh111View Answer on Stackoverflow