title: How include/exclude FormControls from validation in large Angular forms
body: <p>In reactive form you can use <code>AbstractFormControl.disable()</code> when you want to exclude particular FormControl/FormGroup from validation. And you can use <code>AbstractFormControl.enable()</code> to do the oposite. But sometimes it is not as easy with large complex forms.</p>
  
  <p>Consider following form: </p>
  
  <p><a href="https://i.stack.imgur.com/Ftxqc.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/Ftxqc.png" alt="enter image description here"></a></p>
  
  <ul>
  <li>green area is present only if B is checked</li>
  <li>blue area is present only if E is checked</li>
  <li>red area is present only if X is checked</li>
  </ul>
  
  <p>The code for the above picture:</p>
  
  <p><div class="snippet" data-lang="js" data-hide="false" data-console="true" data-babel="false">
  <div class="snippet-code">
  <pre class="snippet-code-js lang-js prettyprint-override"><code>   @Component({
        selector: 'my-app',
        template: `&lt;div [formGroup]="form"&gt;
            &lt;div style="float: right"&gt;
              &lt;label for="ctrlX"&gt;X&lt;/label&gt;
              &lt;input type="checkbox" formControlName="ctrlX" /&gt;
            &lt;/div&gt;
  
            &lt;div class="row"&gt;
              &lt;label for="ctrlA"&gt;A&lt;/label&gt;
              &lt;input type="text" name="ctrlA" formControlName="ctrlA" /&gt;
            &lt;/div&gt;
  
            &lt;div class="row"&gt;
              &lt;label for="ctrlB"&gt;B&lt;/label&gt;
              &lt;input type="checkbox" name="ctrlB" formControlName="ctrlB" /&gt;
            &lt;/div&gt;
  
            &lt;div *ngIf="form.value.ctrlB === true"&gt;
              &lt;div [formGroup]="form.get('detailB')"&gt;
                &lt;div class="row"&gt;
                  &lt;label for="ctrlC"&gt;C&lt;/label&gt;
                  &lt;input type="text" name="ctrlC" formControlName="ctrlC" /&gt;
                &lt;/div&gt;
  
                &lt;div class="row" *ngIf="form.value.ctrlX === true"&gt;
                  &lt;label for="ctrlD"&gt;D&lt;/label&gt;
                  &lt;input type="text" name="ctrlD" formControlName="ctrlD" /&gt;
                &lt;/div&gt;
  
                &lt;div class="row"&gt;
                  &lt;label for="ctrlE"&gt;E&lt;/label&gt;
                  &lt;input type="checkbox" name="ctrlE" formControlName="ctrlE" /&gt;
                &lt;/div&gt;
  
                &lt;div *ngIf="form.value.detailB.ctrlE === true"&gt;
                  &lt;div [formGroup]="form.get('detailB').get('detailE')"&gt;
                    &lt;div class="row"&gt;
                      &lt;label for="ctrlF"&gt;F&lt;/label&gt;
                      &lt;input type="text" name="ctrlF" formControlName="ctrlF" /&gt;
                    &lt;/div&gt;
                  &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;
            &lt;div class="row"&gt;
              &lt;label&gt;&lt;/label&gt;
              &lt;button&gt;Submit&lt;/button&gt;
            &lt;/div&gt;
          &lt;/div&gt;`,
        styleUrls: [ './app.component.css' ]
      })
      export class AppComponent  {
        private form = this.formBuilder.group({
          ctrlA: ['', Validators.required],
          ctrlB: [false],
          detailB: this.formBuilder.group({
            ctrlC: ['', Validators.required],
            ctrlD: ['', Validators.required],
            ctrlE: [false],
            detailE: this.formBuilder.group({
              ctrlF: ['', Validators.required]
            })
          }),
          ctrlX: [true],
        });
  
        constructor(private formBuilder: FormBuilder) {}
      }</code></pre>
  </div>
  </div>
  </p>
  
  <p>Now the thing is, that you don't want to validate something, that is not visible to the user. But the question is: <strong>How to implement this correctly?</strong></p>
  
  <p>Here is what i tried so far.</p>
  
  <p><strong>A</strong>: toggling controls one by one demonstrated in this <a href="https://stackblitz.com/edit/angular-a45hsa?file=src%2Fapp%2Fapp.component.ts" rel="nofollow noreferrer">live example</a><br>
  This works as expected, but there are two downsides:</p>
  
  <ul>
  <li>code is lengthy, unclear and therefore quite error prone in my opinion</li>
  <li>this way, some controls are dependent on more than one condition, so you need to combine the conditions as well as merge the <code>valueChanges</code> observables (for example F is dependent not only on E but on B as well)</li>
  </ul>
  
  <p><strong>B</strong>: toggling parent formGroups instead of particular formControls demonstrated in <a href="https://stackblitz.com/edit/angular-drwpvk?file=src%2Fapp%2Fapp.component.ts" rel="nofollow noreferrer">live example</a><br>
  Problem is that <code>FormGroup.disable()</code> recursively changes status of each descendant which leaves and form in an inconsistent state compared to UI.</p>
  
  <p>In those live examples you can see what in enabled in the textarea on the bottom of the page.</p>