title: Angular Reactive Forms with nested Form Arrays
body: <p>I'm new to Angular 2 and decided the best way to learn would be to go through the official Angular guides.</p>
  
  <p>I went through the Reactive Forms Guide
  <a href="https://angular.io/guide/reactive-forms" rel="noreferrer">https://angular.io/guide/reactive-forms</a></p>
  
  <p>demo link: <a href="https://stackblitz.com/angular/jammvmbrpxle" rel="noreferrer">https://stackblitz.com/angular/jammvmbrpxle</a></p>
  
  <p>While the content was overall pretty good, I'm stuck on how I would go about implementing a more complex Form. In the given example, each Hero has the potential for many addresses. An address itself is a flat object.</p>
  
  <p>What if Addresses had additional information such as the color and type of rooms located at the address.</p>
  
  <pre class="lang-ts prettyprint-override"><code>export class Address {
      street = '';
      city   = '';
      state  = '';
      zip    = '';
      rooms = Room[];
  }
  
  export class Room {
       type = '';
  }
  </code></pre>
  
  <p>so that the form model would look like this...</p>
  
  <pre class="lang-ts prettyprint-override"><code>createForm() {
  this.heroForm = this.fb.group({
    name: '',
    secretLairs: this.fb.array([
        this.fb.group({
            street: '',
            city: '',
            state: '',
            zip: '',
            rooms: this.fb.array([
                this.fb.group({
                   type: ''
            })]),
        })]),
    power: '',
    sidekick: ''
  });
  </code></pre>
  
  <p>}</p>
  
  <p><strong>EDIT - Finalized Code that works with ngOnChanges</strong></p>
  
  <p>hero-detail.component.ts</p>
  
  <pre class="lang-ts prettyprint-override"><code>createForm() {
      this.heroForm = this.fb.group({
        name: '',
        secretLairs: this.fb.array([
          this.fb.group({
            street: '',
            city: '',
            state: '',
            zip: '',
            rooms: this.fb.array([
              this.fb.group({
                type: ''
              })
            ])
          })
        ]),
        power: '',
        sidekick: ''
      });
    }
  
    ngOnChanges() {
      this.heroForm.reset({
        name: this.hero.name,
      });
      this.setAddresses(this.hero.addresses);
    }
  
    setAddresses(addresses: Address[]) {
      let control = this.fb.array([]);
      addresses.forEach(x =&gt; {
        control.push(this.fb.group({
          street: x.street,
          city: x.city,
          state: x.state,
          zip: x.zip,
          rooms: this.setRooms(x) }))
      })
      this.heroForm.setControl('secretLairs', control);
    }
  
    setRooms(x) {
      let arr = new FormArray([])
      x.rooms.forEach(y =&gt; {
        arr.push(this.fb.group({ 
          type: y.type 
        }))
      })
      return arr;
    }
  </code></pre>
  
  <p>hero-detail.component.html  (the nested form array portion)</p>
  
  <pre class="lang-html prettyprint-override"><code>&lt;div formArrayName="secretLairs" class="well well-lg"&gt;
    &lt;div *ngFor="let address of heroForm.get('secretLairs').controls; let i=index" [formGroupName]="i" &gt;
      &lt;!-- The repeated address template --&gt;
      &lt;h4&gt;Address #{{i + 1}}&lt;/h4&gt;
      &lt;div style="margin-left: 1em;"&gt;
        &lt;div class="form-group"&gt;
          &lt;label class="center-block"&gt;Street:
            &lt;input class="form-control" formControlName="street"&gt;
          &lt;/label&gt;
        &lt;/div&gt;
        &lt;div class="form-group"&gt;
          &lt;label class="center-block"&gt;City:
            &lt;input class="form-control" formControlName="city"&gt;
          &lt;/label&gt;
        &lt;/div&gt;
        &lt;div class="form-group"&gt;
          &lt;label class="center-block"&gt;State:
            &lt;select class="form-control" formControlName="state"&gt;
              &lt;option *ngFor="let state of states" [value]="state"&gt;{{state}}&lt;/option&gt;
            &lt;/select&gt;
          &lt;/label&gt;
        &lt;/div&gt;
        &lt;div class="form-group"&gt;
          &lt;label class="center-block"&gt;Zip Code:
            &lt;input class="form-control" formControlName="zip"&gt;
          &lt;/label&gt;
        &lt;/div&gt;
      &lt;/div&gt;
      &lt;br&gt;
      &lt;!-- End of the repeated address template --&gt;
      &lt;div formArrayName="rooms" class="well well-lg"&gt;
        &lt;div *ngFor="let room of address.get('rooms').controls; let j=index" [formGroupName]="j" &gt;
            &lt;h4&gt;Room #{{j + 1}}&lt;/h4&gt;
            &lt;div class="form-group"&gt;
              &lt;label class="center-block"&gt;Type:
                &lt;input class="form-control" formControlName="type"&gt;
              &lt;/label&gt;
            &lt;/div&gt;
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;button (click)="addLair()" type="button"&gt;Add a Secret Lair&lt;/button&gt;
  &lt;/div&gt;
  </code></pre>