title: Structuring Angular2 Forms - How to include conditional form fields that validate
body: <p><strong>The Context</strong></p>
  
  <p>Jecelyn Yeen has an <a href="https://scotch.io/tutorials/how-to-build-nested-model-driven-forms-in-angular-2" rel="nofollow noreferrer">excellent article</a> on how to organize nested forms in Angular2.</p>
  
  <p>In her example, she uses an array to display multiple Address form sub-components so that the user can endlessly click "Add Address" and the form will still validate correctly. I would like to do something similar, but instead of having an array of sub-forms, instead display a different sub-form depending on the value of a dropdown.</p>
  
  <p>I try to structure my code similarly to hers, except instead of returning a form builder array, I use a form group for each subform I would like to display. When a dropdown option is selected, I delete the form groups that should not be displayed, and recreate the ones that should be. The problem I'm getting is that when structured this way, the parent form does not pick up changes within the child form.</p>
  
  <p><strong>The Code</strong></p>
  
  <p>ts:</p>
  
  <pre><code>public showNameForm: boolean = false;
  public showAddressForm: boolean = false;
  public showPhoneNumberForm: boolean = false;
  
  constructor (fb: FormBuilder) {
    this.myForm = fb.group({
      nameInfo: this.getNameForm(),
      addressInfo: this.getAddressForm(),
      phoneNumberInfo: this.getPhoneNumberForm()
    });
  }
  
  getNameForm () {
    return this.fb.group({
      name: ["", Validators.required]
    });
  }
  
  getAddressForm () {
    return this.fb.group({
      address1: ["", Validators.required],
      address2: ["", Validators.required],
      city: ["", Validators.required],
      state: ["", Validators.required],
      zipcode: ["", Validators.required]
    });
  }
  
  getPhoneNumberForm () {
    return this.fb.group({
      phone: ["", Validators.required]
    });
  }
  
  handleDropdownSelect (value) {
    if(value === 1) {
      this.showNameForm = true;
  
      this.myForm.controls['nameInfo'] = this.getNameForm();
      delete this.myForm.controls['addressInfo'];
      delete this.myForm.controls['phoneNumberInfo'];
    }
    // Similar for other cases, e.g. if value is 2, only show addressInfo
  }
  </code></pre>
  
  <p>html:</p>
  
  <pre><code>&lt;form [formGroup]="myForm"&gt;
    &lt;div [formGroupName]="'nameInfo'" *ngIf="showNameForm"&gt;
      &lt;input type="text" formControlName="name" /&gt;
    &lt;/div&gt;
    &lt;!-- Similar for other fields --&gt;
    &lt;!-- ... --&gt;
    &lt;button [ngClass]="{disabled: !myForm.valid}"&gt;Submit&lt;/button&gt;
  &lt;/form&gt;
  </code></pre>
  
  <p>Doing this, the submit button is always remaining invalid, even after I type all the required text. Inspecting the form object with the Chrome debugger, I see that <code>myForm.value</code> is equal to</p>
  
  <pre><code>{
    nameInfo: {
      name: ""
    }
  }
  </code></pre>
  
  <p>In other words, the text I type into the sub-form groups never gets picked up by the parent form. But I can see that <code>myForm.controls.nameInfo</code> does have a value with the correct information, and the same thing when the others are selected. All of these properties have a <code>valid</code> property of <code>true</code>. Yet, the parent form does not pick up these changes unless I manually call <code>myForm.updateValueAndValidity()</code>. This is not ideal, since I would like for the form to appear as valid as soon as it becomes valid, without having to add my own event listener to make it happen.</p>