Matching password and confirm password is one of the commonly required functionality in many applications.We are going to implement it like this

When passwords are not matching

When they are matching

 

 

We can achieve this functionality in multiple ways in Angular 12, 13+ applications. We will see how to do it in the following three ways

  • By using Template Reference Variables
  • By using Template Driven Forms Module
  • By using Reactive Forms Module

Password & Confirm Password Matching Functionality in Angular 12 / 13 by using Template Reference Variables

In this way, we will see how to do it only by using Template Reference Variables without using any forms module

HTML:

<!-- Password & Confirm Password without any Forms Module -->
<div class="mb-3">
    <label for="password" class="form-label">Password</label>
    <input type="password" class="form-control" id="password" #pw>
</div>

<div class="mb-3">
    <label for="cPassword" class="form-label">Confirm Password</label>
    <input type="password" [ngClass]='confirmPasswordClass' id="cPassword" #cpw
        (keyup)='checkPasswords(pw.value, cpw.value)'>
</div>
<div *ngIf='!passwordsMatching && isConfirmPasswordDirty'>
    Passwords did not match
</div>

In the previous HTML code, we have two input elements of type password for password and confirm password fields. We added template reference variable #pw to password field and #cpw for confirm password element.

When the user enters something in the confirm password input element, we are passing the values of pw and cpw to checkPasswords function.

We have also used ngClass directive on confirm password element so that we can change the CSS classes applied on this element dynamically based on whether it is matching with password or not.

TypeScript:

passwordsMatching: boolean = false;
  isConfirmPasswordDirty: boolean = false;
  confirmPasswordClass: string = 'form-control';

checkPasswords(pw: string, cpw: string) {
    this.isConfirmPasswordDirty = true;
    if (pw === cpw) {
      this.passwordsMatching = true;
      this.confirmPasswordClass = 'form-control is-valid';
    } else {
      this.passwordsMatching = false;
      this.confirmPasswordClass = 'form-control is-invalid'
    }
  }

The above code is almost straight explanatory. When the passed values of password and confirm password are equal we are setting the value of property passwordsMatched to true else false. We are also changing the values of CSS class names to be applied on the confirm password element based on whether they have matched.

We have also used a property named isConfirmPasswordDirty (whether user have modified the value of confirm password), so that we can show the error message only when the user is entering a value in confirm password.

Matching Password and Confirm Password in Angular 13+ applications using Template Driven Forms

Now, we will see how to implement the same functionality using Template Driven Forms

First import FormsModule in your module.ts file

import { FormsModule } from '@angular/forms';
...
imports: [
    ...
    FormsModule,
    ...
  ]

HTML:

<!-- Password & Confirm Password with Template Driven Forms Module -->

<form #myForm="ngForm">
    <div class="mb-3">
        <label for="password" class="form-label">Password</label>
        <input type="password" class="form-control" id="password" ngModel name="pw">
    </div>

    <div class="mb-3">
        <label for="cPassword" class="form-label">Confirm Password</label>
        <input type="password" [ngClass]='confirmPasswordClass' id="cPassword" ngModel name="cpw" #cPassword="ngModel"
            (ngModelChange)='checkPasswordsWithTemplateDrivenForms(myForm)'>
    </div>
    <div *ngIf='!passwordsMatching && cPassword.dirty '>
        Passwords did not match
    </div>

</form>

Like before, we have two input fields for password and confirm password. We have created a template reference variable #myForm on form element and assigned ngForm which comes with FormsModule to it which adds various form related properties and methods to myForm variable to handle the form efficiently.

We then added the directives ngModel on input elements so that the elements gets attached to the form as its controls in which they are in. Since we do not want to handle the input elements individually, we added name property to them.

We did event binding with the event ngModelChange which comes from FormsModule and gets triggered whenever the value of the input element on which we did event binding changes. We are passing the entire form to this function (if the form is big, you pass the values of required input elements like myForm.value[“pw”]) .

The ngClass works exactly like in the first example

TS File

checkPasswordsWithTemplateDrivenForms(form: NgForm) {
    if (form.value['pw'] === form.value['cpw']) {
      this.passwordsMatching = true;
      this.confirmPasswordClass = 'form-control is-valid';
    } else {
      this.passwordsMatching = false;
      this.confirmPasswordClass = 'form-control is-invalid'
    }
  }

The above TypeScript code is almost like the first example, the only change is we are comparing the values of password and confirm password taken from the myForm.value object.

Password and Confirm Password matching in Angular 13 application using Reactive Forms Module

Reactive Forms offers the most sophisticated ways to handle simple and advanced forms. Unlike Template Reference Variables and Template Driven Forms where we did most of the coding in the HTML, we do it inside the TS file in reactive forms.

First import reactive forms module in your module file and add it to the imports array

import { ReactiveFormsModule } from '@angular/forms';
...
imports: [
   ...
    ReactiveFormsModule
    ...
  ]

TS File:

First we import FormGroup and FormBuilder from Angular forms and create our form like this

import { FormGroup, FormBuilder } from '@angular/forms';

...
pwForm: FormGroup;
...
constructor(private fb: FormBuilder) {
    this.pwForm = this.fb.group({
      password: '',
      confirmPassword: ''
    });
   ...
  }

We have imported built-in Angular service FormBuilder which makes creating forms very easy and injected it through the constructor. We then initialized pwForm inside the constructor (some developers prefers to do it inside ngOnInit life cycle method, if you want, you can do it there as well).

HTML:

<!-- Password & Confirm Password with Reactive Forms Module -->

<form [formGroup]="pwForm">
    <div class="mb-3">
        <label for="password" class="form-label">Password</label>
        <input type="password" class="form-control" id="password" formControlName="password">
    </div>

    <div class="mb-3">
        <label for="cPassword" class="form-label">Confirm Password</label>
        <input type="password" [ngClass]='confirmPasswordClass' id="cPassword" formControlName="confirmPassword">
    </div>
    <div *ngIf='!passwordsMatching && pwForm.controls["confirmPassword"].dirty '>
        Passwords did not match
    </div>

</form>

In the code above, to bind the form we created earlier inside the ts file to HTML, we did property binding on the form element. We then added the formControlName to the input elements.

Now to check the values of password and confirm password when the user enters a value inside confirm password element, we can listen to the value changes of confirm password by subscribing to it and compare both inside it.

TS file:

...
 this.pwForm.controls['confirmPassword'].valueChanges.subscribe((val) => {
      if (this.pwForm.controls['password'].value === val) {
        this.passwordsMatching = true;
        this.confirmPasswordClass = 'form-control is-valid';
      } else {
        this.passwordsMatching = false;
        this.confirmPasswordClass = 'form-control is-invalid'
      }
    })
...

The code above is again self explanatory. We have subscribed to the value changes of confirm password form control and we checked their equality in it. If you have initialized your form inside constructor, then you can place the above code in either constructor or ngOnInit life cycle hook. If you have initialized the form in ngOnInit life cycle method, then do not keep the above code inside the constructor because your form will not be available yet at that point.

Further enhancements:

In real time applications you may have to consider many more permutations and combinations such as, what if the user directly enters a value in the confirm password or what if the user changes the value of password after entering and matching with confirm password so on.

Check this post, if you want to implement the same using Vanilla JavaScript Password and Confirm Password matching in JavaScript