title: Angular 6 reactive form validation not working with custom validator
body: <p>So I created a custom validator to validate that a "New Password" field and a "Confirm Password" field match. On the component level, it works great. The error message only shows when the two inputs don't match.</p>
  
  <p>The problem is, I disable the submit button until the form is valid, but when I use this custom validator, the form as a whole, never passes validation. When for form is filled out, all of the component validations pass, but the form validation does not.</p>
  
  <p>What am I missing here?</p>
  
  <p>The custom validator code looks like this:</p>
  
  <pre><code>import {FormGroup, ValidationErrors, ValidatorFn} from "@angular/forms";
  
  export const matchingInputsValidator: ValidatorFn = (control: FormGroup): ValidationErrors | null =&gt; {
    let pass = control.get('NewPassword').value;
    let confirmPass = control.get('ConfirmPassword').value;
    return pass === confirmPass ? { matchingInputs: true } : { matchingInputs: false };
  };
  </code></pre>
  
  <p>I import the custom validator into my component and declare my form controls in the component like this:</p>
  
  <pre><code>expiredPasswordForm: FormGroup;
  oldPassword = new FormControl('', Validators.compose([Validators.required, Validators.minLength(4)]));
  newPassword = new FormControl('', Validators.compose([Validators.required, Validators.minLength(4)]));
  confirmPassword = new FormControl('', Validators.compose([Validators.required, Validators.minLength(4)]));
  </code></pre>
  
  <p>And in my ngOnInit() lifecycle hook, I create my form group like this:</p>
  
  <pre><code>this.expiredPasswordForm = this.fb.group({
        'OldPassword': this.oldPassword,
        'NewPassword': this.newPassword,
        'ConfirmPassword': this.confirmPassword
      }, { validator: matchingInputsValidator});
  </code></pre>
  
  <p>And my HTML for my form looks like this:</p>
  
  <pre><code>&lt;form [formGroup]="expiredPasswordForm" ngNoForm action="" method="post" class="form-horizontal"&gt;
  
          &lt;label for="oldPassword" class="col-sm-4 col-md-6 col-lg-6 col-xl-6 control-label" translate&gt;Old Password&lt;/label&gt;
          &lt;input [formControl]="oldPassword" type="password" class="form-control" id="oldPassword"
                 placeholder="Old Password" name="OldPassword" [ngClass]="{'is-invalid':oldPassword.invalid &amp;&amp; (oldPassword.dirty || oldPassword.touched)}"&gt;
          &lt;div *ngIf="oldPassword.invalid &amp;&amp; (oldPassword.dirty || oldPassword.touched)" class="invalid-feedback"&gt;
            &lt;span *ngIf="oldPassword.errors.required"&gt;Old Password is required&lt;/span&gt;
          &lt;/div&gt;
  
          &lt;label for="newPassword" class="col-sm-4 col-md-6 col-lg-6 col-xl-6 control-label mt-2" translate&gt;New Password&lt;/label&gt;
          &lt;input [formControl]="newPassword" type="password" class="form-control" id="newPassword"
                 placeholder="New Password" name="NewPassword" [ngClass]="{'is-invalid':newPassword.invalid &amp;&amp; (newPassword.dirty || newPassword.touched)}"&gt;
          &lt;div *ngIf="newPassword.invalid &amp;&amp; (newPassword.dirty || newPassword.touched)" class="invalid-feedback"&gt;
            &lt;span *ngIf="newPassword.errors.required"&gt;A new password is required&lt;/span&gt;
          &lt;/div&gt;
  
          &lt;label for="confirmPassword" class="col-sm-4 col-md-6 col-lg-6 col-xl-6 control-label mt-2" translate&gt;Confirm Password&lt;/label&gt;
          &lt;input [formControl]="confirmPassword" type="password" class="form-control" id="confirmPassword"
                 placeholder="Confirm Password" name="ConfirmPassword" [ngClass]="{'is-invalid':confirmPassword.invalid &amp;&amp; (confirmPassword.dirty || confirmPassword.touched)}"&gt;
          &lt;div *ngIf="confirmPassword.invalid &amp;&amp; (confirmPassword.dirty || confirmPassword.touched)" class="invalid-feedback"&gt;
            &lt;span *ngIf="confirmPassword.errors.required"&gt;You must confirm your new password!&lt;/span&gt;
          &lt;/div&gt;
          &lt;div *ngIf="!expiredPasswordForm.errors?.matchingInputs"&gt;
            &lt;span class="form-error-message"&gt;Passwords do not match!&lt;/span&gt;
          &lt;/div&gt;
  
          &lt;div class="text-center"&gt;
            &lt;button [disabled]="!expiredPasswordForm.valid" type="submit" class="btn btn-primary mt-4 mb-2"&gt;Update Password&lt;/button&gt;
          &lt;/div&gt;
  
        &lt;/form&gt;
  </code></pre>
  
  <p>I hope this is enough information. Why does this work on the component level, but not on the form level? Thank you in advance!</p>