Search code examples
angularformsangular-reactive-formsformgroupsangular2-formbuilder

Angular Reactive Form - Nested objects within form


I've got a working nested object on my form as follows:

this.form = this.fb.group({
  name:(),
  age:(),
  address: this.fb.group({
    city:(),
    street:()
  })
})

However, I want the possibility of having multiple addresses, in which case I would want the JSON to look like this:

{
  "name": "name",
  "age": "age",
  "address":
  {
    "city": "cityA",
    "street": "streetA"
  },
  {
    "city": "cityB",
    "street": "streetB"
  }

How do I go about doing that?


Solution

  • Your JSON is not valid, it should be:

    {
      name: 'name',
      age: 'age',
      address: [
        {
          city: 'cityA',
          street: 'streetA',
        },
        {
          city: 'cityB',
          street: 'streetB',
        },
      ],
    }
    

    address needs to use FormArray. The below code shows:

    1. How to build a Reactive form with FormArray.
    2. How to add and patch value for FormGroup into FormArray.
    ngOnInit() {
      this.form = this.fb.group({
        name: [],
        age: [],
        address: this.fb.array([]),
      });
    
      this.form.patchValue(this.data);
      this.addAddress();
    }
    
    addAddress() {
      for (let address of this.data.address) {
        let group = this.fb.group({
          city: [],
          street: [],
        });
    
        group.patchValue(address);
        this.addresses.controls.push(group);
      }
    }
    
    get addresses(): FormArray {
      return this.form.controls.address as FormArray;
    }
    

    The HTML template should look as below:

    <form [formGroup]="form">
      <div>Name: <input type="text" formControlName="name" /></div>
      <div>Age: <input type="number" formControlName="age" /></div>
    
      <div
        *ngFor="let controls of addresses.controls; let i = index"
        formArrayName="address"
      >
        <div [formGroupName]="i">
          <div>City: <input type="text" formControlName="city" /></div>
          <div>Street: <input type="text" formControlName="street" /></div>
        </div>
    
        <hr />
      </div>
    </form>
    

    Sample StackBlitz Demo


    Would suggest having a read and doing the practical by following Angular FormArray: Complete Guide.