Custom Validator to match Password and Confirm Password in Angular

Creating a custom validator to match the password and confirm password fields in an Angular form is a common requirement for many applications.

Introduction to Custom Validators:
  • Custom validators in Angular allow you to extend the default validation capabilities and create specific rules tailored to your needs.
  • They can be used for various purposes, such as ensuring passwords match, validating email formats, or checking for forbidden values.


Signup Model
import { FormControl } from "@angular/forms";

export interface SignupFormModel{
  name: FormControl<string | null>;
  email: FormControl<string | null>;
  password: FormControl<string | null>;
  confirmPassword: FormControl<string | null>;
}


Ts File
  public signupFormGroup: FormGroup<SignupFormModel> = new FormGroup<SignupFormModel>({
    name: new FormControl(null, [Validators.required]),
    email: new FormControl(null, [Validators.required, Validators.pattern(/[a-zA-Z0-9_\-\.]+@[a-z]+\.[c][o][m]/)]),
    password: new FormControl(null, [Validators.required, Validators.pattern(/(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[!@#$%^&*()_+]).{8,}/)]),
    confirmPassword: new FormControl(null, [Validators.required]),
  }, { validators: this.customPasswordMatching.bind(this) });

  public customPasswordMatching(control: AbstractControl): ValidationErrors | null {
    const password = control.get('password')?.value;
    const confirmPassword = control.get('confirmPassword')?.value;
    
    return password === confirmPassword ? null : { passwordMismatchError: true };
  }


HTML File
  <div class="center-container container w-50 mt-2" style="width: 100%">
  <div class="card">
    <div class="card-body" style="background-color: antiquewhite">
      <form [formGroup]="signupFormGroup">
        <div class="mb-2" style="height: 50px; margin-top: -8px">
          <div class="row">
            <div class="col col-md-6">
              <label class="form-control-sm">Name</label>
            </div>
            <div class="col">
              <input type="text" class="form-control form-control-sm" formControlName="name" placeholder="Enter name"/>
              <span *ngIf="(signupFormGroup.controls.name.dirty || signupFormGroup.controls.name.touched)" class="form-control-sm text-danger">
                <span style="font-size: 12px; margin-top: 0px" *ngIf="signupFormGroup.controls.name.errors?.['required']">
                  *Name is Required
                </span>
              </span>
            </div>
          </div>
        </div>

        <div class="mb-2" style="height: 50px">
          <div class="row">
            <div class="col">
              <label class="form-control-sm">Email address</label>
            </div>
            <div class="col">
              <input type="email" class="form-control form-control-sm" formControlName="email" placeholder="name@example.com"/>
              <span *ngIf="(signupFormGroup.controls.email.dirty || signupFormGroup.controls.email.touched)" class="form-control-sm text-danger">
                <span *ngIf="signupFormGroup.controls.email.errors?.['required']">
                  *Email is Required
                </span>
                <span *ngIf="signupFormGroup.controls.email.errors?.['pattern']">
                  *Enter Valid Mail
                </span>
              </span>
            </div>
          </div>
        </div>

        <div class="mb-2" style="height: 50px">
          <div class="row">
            <div class="col col-md-6">
              <label class="form-control-sm">Password</label>
            </div>
            <div class="col">
              <input type="password" class="form-control form-control-sm" placeholder="password" formControlName="password"/>
              <span *ngIf="(signupFormGroup.controls.password.dirty || signupFormGroup.controls.password.touched)" class="form-control-sm text-danger">
                <span *ngIf="signupFormGroup.controls.password.errors?.['required']">
                  *Password is Required
                </span>
              </span>
            </div>
          </div>
        </div>

        <div class="mb-2" style="height: 50px">
          <div class="row">
            <div class="col col-md-6">
              <label class="form-control-sm">Confirm Password</label>
            </div>
            <div class="col">
              <input type="password" class="form-control form-control-sm" placeholder="Confirm Password" formControlName="confirmPassword"/>
              <span *ngIf="(signupFormGroup.controls.confirmPassword.dirty || signupFormGroup.controls.confirmPassword.touched)" class="form-control-sm text-danger">
                <span *ngIf="signupFormGroup.controls.confirmPassword.errors?.['required']; else passMismatch">
                  *Confirm Password is Required
                </span>
                <ng-template #passMismatch>
                  <span *ngIf="signupFormGroup.errors?.['passwordMismatchError']">
                    *Password Doesn't matches
                  </span>
                </ng-template>
              </span>
            </div>
          </div>
        </div>

        <div class="row container justify-content-center">
          <button type="submit" class="btn btn-primary" (keydown.enter)="singupUser()" (click)="singupUser()">
            Register Employee
          </button>

          <button *ngIf="isShowSbnt" class="btn btn-primary" type="button" disabled>
            <span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span>
            <span class="sr-only">Loading...</span>
          </button>
        </div>
      </form>
    </div>
  </div>
</div>

Popular posts from this blog

Enhancing Express.js Requests with TypeScript: Adding User Objects and More

How to Avoid Page Changes When You Have Unsaved Changes in Angular