angularangular-reactive-formsangular-custom-validators

Angular Reactive form not updating when FormGroup has new error


So I declare my FormGroup in ngOnInit() and that calls my validator function to ensure that password and confirmPassword fields are matching as so

My typescript

regForm: FormGroup;
  constructor() { }

  ngOnInit() {
    this.regForm = new FormGroup({
      userName: new FormControl('Mark', Validators.required),
      email: new FormControl(null, [Validators.required, Validators.email]),
      password: new FormControl(null, [Validators.required, Validators.minLength(8)]),
      confirmPassword: new FormControl(null, Validators.required),
      mobile: new FormControl(null, [Validators.required, Validators.minLength(10)]),
    }, this.passwordMatchingValid);
  }

  // validators return null if the condition is valid and a json object {key: value} if condition is false
  passwordMatchingValid(fg: FormGroup) : Validators
  {
    return fg.get('password').value === fg.get('confirmPassword').value ? null :
    {
      // {key : value}
      notmatched: true
    };
  }

All the fields have their own getter method as well and everything works fine except for one thing. My confirm password field never seems to recognize the conditions being met when passwords do not match, they will complain if there is nothing in the field since it is required, but as soon as I add a single value in the input the error messages vanish and it doesnt trigger the second span like it should.

My html

          <label for="cpassword" class="form-label">Confirm Password</label>
          <input type="password" class="form-control" formControlName="confirmPassword">

          <span *ngIf="!confirmPassword.valid && confirmPassword.touched" class="error-block">
            <span *ngIf="confirmPassword.hasError('required')">
              Please confirm password
            </span>

            <!-- Check the passwordMatchingValid method, because validators return null if the conditon is true, it will not be detected as an error -->
            <span *ngIf="confirmPassword.valid && regForm.hasError('notmatched')">
              Password not matched
            </span>
          </span>

Solution

  • The first ngIf checks so that confirmPassword is not valid. The second ngIf is in the same span and checks if it is valid.

    If it is invalid it will never be valid.

    Move the last above the password not matched span.

    <span *ngIf="!regForm.controls.confirmPassword.valid && regForm.controls.confirmPassword.touched" class="error-block">
         <span *ngIf="regForm.controls.confirmPassword.hasError('required')">
              Please confirm password
         </span>
    </span> <-- move the last span here instead -->
    <span *ngIf="regForm.controls.confirmPassword.valid && regForm.hasError('notmatched')">
       Password not matched
    </span>