109

I want to perform password and confirm password validations using material components only,and an error message below the confirm password field if confirm password field doesn't match And if it is empty.Tried many resources unable to achieve.

Tried this video too.

This is the material component i am looking for

enter image description here

HTML

     <mat-form-field >
        <input matInput  placeholder="New password" [type]="hide ? 'password' 
          : 'text'" [formControl]="passFormControl" required>
        <mat-icon matSuffix (click)="hide = !hide">{{hide ? 'visibility' : 
          'visibility_off'}}</mat-icon>
        <mat-error *ngIf="passFormControl.hasError('required')">
            Please enter your newpassword
         </mat-error>
      </mat-form-field>

      <mat-form-field >
         <input matInput  placeholder="Confirm password" [type]="hide ? 
              'password' : 'text'" [formControl]="confirmFormControl" 
                    required>
         <mat-icon matSuffix (click)="hide = !hide">{{hide ? 'visibility' : 
                'visibility_off'}}</mat-icon>
         <mat-error *ngIf="confirmFormControl.hasError('required')">
          Confirm your password
          </mat-error>
      </mat-form-field>

TS

     import {Component, OnInit } from '@angular/core';
     import {FormControl, FormGroupDirective, NgForm, Validators} from 
             '@angular/forms';
     import {ErrorStateMatcher} from '@angular/material/core';

     @Component({
            selector: 'asd-set-pass',
            templateUrl: './set-pass.component.html',
             styleUrls: ['./set-pass.component.css']
         })

       passFormControl = new FormControl('', [
            Validators.required,
        ]);
        confirmFormControl = new FormControl('', [
            Validators.required,
            ]);

             hide =true;

       }

It's validating the following conditions fine 1)If password and confirm password fields are empty its showing error text.

I want to compare to fields in (.ts) file like how its validating for empty field, and an error to come if confirm password field is empty.

Pang
  • 9,564
  • 146
  • 81
  • 122
Shankar
  • 2,565
  • 8
  • 29
  • 56

13 Answers13

200

This question could be solved with a combination of these two answers: https://stackoverflow.com/a/43493648/6294072 and https://stackoverflow.com/a/47670892/6294072

So first of all, you would need a custom validator for checking the passwords, that could look like this:

checkPasswords: ValidatorFn = (group: AbstractControl):  ValidationErrors | null => { 
  let pass = group.get('password').value;
  let confirmPass = group.get('confirmPassword').value
  return pass === confirmPass ? null : { notSame: true }
}

and you would create a formgroup for your fields, instead of just two form controls, then mark that custom validator for your form group:

this.myForm = this.fb.group({
  password: ['', [Validators.required]],
  confirmPassword: ['']
}, { validators: this.checkPasswords })

and then as mentioned in other answer, the mat-error only shows if a FormControl is invalid, so you need an error state matcher:

export class MyErrorStateMatcher implements ErrorStateMatcher {
  isErrorState(control: FormControl | null, form: FormGroupDirective | NgForm | null): boolean {
    const invalidCtrl = !!(control?.invalid && control?.parent?.dirty);
    const invalidParent = !!(control?.parent?.invalid && control?.parent?.dirty);

    return invalidCtrl || invalidParent;
  }
}

in the above you can tweak when to show error message. I would only show message when the password field is touched. Also I would like above, remove the required validator from the confirmPassword field, since the form is not valid anyway if passwords do not match.

Then in component, create a new ErrorStateMatcher:

matcher = new MyErrorStateMatcher();

Finally, the template would look like this:

<form [formGroup]="myForm">
  <mat-form-field>
    <input matInput placeholder="New password" formControlName="password" required>
    <mat-error *ngIf="myForm.hasError('required', 'password')">
      Please enter your new password
    </mat-error>
  </mat-form-field>

  <mat-form-field>
    <input matInput placeholder="Confirm password" formControlName="confirmPassword" [errorStateMatcher]="matcher">
    <mat-error *ngIf="myForm.hasError('notSame')">
      Passwords do not match
    </mat-error>  
  </mat-form-field>
</form>

Here's a demo for you with the above code: StackBlitz

AT82
  • 71,416
  • 24
  • 140
  • 167
  • 4
    The group validator should be {validator: this.checkPasswords}, without the s :) – Zhenyi Zhang Jan 04 '19 at 09:55
  • 1
    We can use this.myFormGroup.setValidators(this.checkPasswords); – rickz Jan 07 '19 at 20:13
  • 4
    You might wanna add `control.touched` in the `MyErrorStateMatcher ` class to not make the error pop up even before the user tried to re-enter the password. – Muhammad bin Yusrat Jan 21 '19 at 06:59
  • 1
    @MuhammadbinYusrat True. But I followed how OP "wanted" to show the message, and also commented in my answer that `in the above you can tweak when to show error message. I would only show message when the password field is touched` But I agree with what you are saying :) – AT82 Jan 21 '19 at 07:03
  • @AJT_82 Excellent! :) – Muhammad bin Yusrat Jan 21 '19 at 07:04
  • @AJT_82 Nice and Excellent answer. – Rajendrasinh Parmar Feb 22 '19 at 20:41
  • 7
    One issue I had was that the control remains invalid event when the passwords do match. Changing the MyErrorStateMatcher last line solved it: `return control.parent.errors && control.parent.errors['notSame']` – Assaf S. May 15 '19 at 07:14
  • @AssafS thanks for the addition I think what you mean is `return control.parent.errors && control.parent.errors && control.touched && ( invalidCtrl || invalidParent );` – Mahmoud Kassem Aug 08 '19 at 11:11
  • `['notSame']` in MyErrorStateMatcher is unnecessary – Mahmoud Kassem Aug 08 '19 at 11:13
  • 1
    `myForm.hasError('notSame')` always returns `false` in my case – Shekhar Sahu Aug 21 '19 at 10:49
  • The `ErrorStateMatcher` is redundant. Add the customer validator to the confirmPassword control instead. – jenson-button-event Oct 12 '20 at 13:03
  • https://stackblitz.com/edit/angular-yhbuqn-5skkyu?file=app%2Finput-error-state-matcher-example.ts It's working here on stackblitz. But when I implement the same code in my angular application then it is not working. Any workaround please. – Navneet Srivastava Oct 22 '20 at 01:05
  • Had to change `const invalidCtrl = !!(control?.invalid && control?.parent?.dirty);` this line int the MyErrorStateMatcher to `control?.touched || control?.parent?.dirty` to make sure that the confirmation field is not showing error without being modified. – Ankit Wadhwana Jun 24 '21 at 11:36
  • why this forces you to put a fixed name to 2 field, password and confirmPassword should not be those a validator parameter ? – Lucke Apr 04 '22 at 09:37
  • I did customize the implementation to what I wanted and its cool. Thanks @AT82 – D_Edet Aug 31 '22 at 22:01
60

You can simply use password field value as a pattern for confirm password field.

For Example:

<div class="form-group">
    <input type="password" [(ngModel)]="userdata.password" name="password" placeholder="Password" class="form-control"
        required #password="ngModel" pattern="(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{8,}" />
    <div *ngIf="password.invalid && (myform.submitted || password.touched)" class="alert alert-danger">
        <div *ngIf="password.errors.required"> Password is required. </div>
        <div *ngIf="password.errors.pattern"> Must contain at least one number and one uppercase and lowercase letter,
            and at least 8 or more characters.</div>
    </div>
</div>

<div class="form-group">
    <input type="password" [(ngModel)]="userdata.confirmpassword" name="confirmpassword" placeholder="Confirm Password"
        class="form-control" required #confirmpassword="ngModel" pattern="{{ password.value }}" />
    <div *ngIf=" confirmpassword.invalid && (myform.submitted || confirmpassword.touched)" class="alert alert-danger">
        <div *ngIf="confirmpassword.errors.required"> Confirm password is required. </div>
        <div *ngIf="confirmpassword.errors.pattern"> Password & Confirm Password does not match.</div>
    </div>
</div>
David Wolf
  • 1,400
  • 1
  • 9
  • 18
Alok Mali
  • 2,821
  • 2
  • 16
  • 32
41

First we create the validator:

export default class CustomValidators {
  static match(controlName: string, matchControlName: string): ValidatorFn {
    return (controls: AbstractControl) => {
      const control = controls.get(controlName);
      const matchControl = controls.get(matchControlName);

      if (!matchControl?.errors && control?.value !== matchControl?.value) {
        matchControl?.setErrors({
          matching: {
            actualValue: matchControl?.value,
            requiredValue: control?.value
          }
        });
        return { matching: true };
      }
      return null;
    };
  }
}

Then we use it in form like this:

this.form = this.formBuilder.group(
  {
    password: [undefined, [Validators.required]],
    passwordConfirm: [undefined, [Validators.required]]
  }،
  {
    validators: [CustomValidators.match('password', 'passwordConfirm')]
  }
);

OUTDATED, please use the code above.

The simplest way imo:

(It can also be used with emails for example)

public static matchValues(
    matchTo: string // name of the control to match to
  ): (AbstractControl) => ValidationErrors | null {
    return (control: AbstractControl): ValidationErrors | null => {
      return !!control.parent &&
        !!control.parent.value &&
        control.value === control.parent.controls[matchTo].value
        ? null
        : { isMatching: false };
    };
}

In your Component:

this.SignUpForm = this.formBuilder.group({

password: [undefined, [Validators.required]],
passwordConfirm: [undefined, 
        [
          Validators.required,
          matchValues('password'),
        ],
      ],
});

Follow up:

As others pointed out in the comments, if you fix the error by fixing the password field the error won't go away, Because the validation triggers on passwordConfirm input. This can be fixed by a number of ways. I think the best is:

this.SignUpForm .controls.password.valueChanges.subscribe(() => {
  this.SignUpForm .controls.confirmPassword.updateValueAndValidity();
});

On password change, revliadte confirmPassword.

Zahema
  • 1,345
  • 2
  • 19
  • 35
  • This is the most fantastic answer, Thank you bro. – Eyad Farra Aug 02 '19 at 07:25
  • 3
    it's a great solution but it's not complete if you go back to password field and change the password, confirmPassword Field does not throw the respective error. – Brayan Loayza Jan 07 '20 at 17:49
  • @BrayanLoayza I think that can be solved if the matching is two way. `matchValues('passwordConfirm')` & `matchValues('password')` – Zahema Jan 08 '20 at 14:07
  • 1
    The problem is if you fix the error by changing the password field it doesn't clear the error on passwordConfirm field – BrunoLM Mar 10 '20 at 13:13
  • 1
    @BrunoLM You are correct, thank you, please check the updated answer -the follow up section. – Zahema Mar 10 '20 at 14:32
  • Which validator name can I use to dispplay the error in the form? Currently I'm showing this, it's not recognizing matchTo.
    Passwords don't match
    – Shivani Aug 04 '20 at 09:08
  • 1
    @Shivani It should be `isMatching` if you followed my example. `
    `
    – Zahema Aug 06 '20 at 11:34
  • 1
    This should be answer. This way can validate when user type in passwordConfirm. The answer has marked must wait until form submits to validate – congle Feb 18 '21 at 10:01
  • You could also detect the change in the template with ```(change)="form.controls.confirmPassword.updateValueAndValidity()" ``` – Jonathan Mar 15 '21 at 04:11
15

Single method for Reactive Forms

TYPESCRIPT

// All is this method
onPasswordChange() {
  if (this.confirm_password.value == this.password.value) {
    this.confirm_password.setErrors(null);
  } else {
    this.confirm_password.setErrors({ mismatch: true });
  }
}

// getting the form control elements
get password(): AbstractControl {
  return this.form.controls['password'];
}

get confirm_password(): AbstractControl {
  return this.form.controls['confirm_password'];
}

HTML

// PASSWORD FIELD
<input type="password" formControlName="password" (change)="onPasswordChange()"/>

// CONFIRM PASSWORD FIELD
<input type="password" formControlName="confirm_password" (change)="onPasswordChange()" />

// SHOW ERROR IF MISMATCH
<span *ngIf="confirm_password.hasError('mismatch')">Password do not match.</span>
WasiF
  • 26,101
  • 16
  • 120
  • 128
12

In case you have more than just Password and Verify Password fields. Like this the Confirm password field will only highlights error when user write something on this field:

validators.ts

import { FormGroup, FormControl, Validators, FormBuilder, FormGroupDirective, NgForm } from '@angular/forms';
import { ErrorStateMatcher } from '@angular/material/core';

export const EmailValidation = [Validators.required, Validators.email];
export const PasswordValidation = [
  Validators.required,
  Validators.minLength(6),
  Validators.maxLength(24),
];

export class RepeatPasswordEStateMatcher implements ErrorStateMatcher {
  isErrorState(control: FormControl | null, form: FormGroupDirective | NgForm | null): boolean {
    return (control && control.parent.get('password').value !== control.parent.get('passwordAgain').value && control.dirty)
  }
}
export function RepeatPasswordValidator(group: FormGroup) {
  const password = group.controls.password.value;
  const passwordConfirmation = group.controls.passwordAgain.value;

  return password === passwordConfirmation ? null : { passwordsNotEqual: true }     
}

register.component.ts

import { FormGroup, FormControl, Validators, FormBuilder} from '@angular/forms';
import { EmailValidation, PasswordValidation, RepeatPasswordEStateMatcher, RepeatPasswordValidator } from 'validators';

...

form: any;
passwordsMatcher = new RepeatPasswordEStateMatcher;


constructor(private formBuilder: FormBuilder) {
    this.form = this.formBuilder.group ( {
      email: new FormControl('', EmailValidation),
      password: new FormControl('', PasswordValidation),
      passwordAgain: new FormControl(''),
      acceptTerms: new FormControl('', [Validators.requiredTrue])
    }, { validator: RepeatPasswordValidator });
  }

...

register.component.html

<form [formGroup]="form" (ngSubmit)="submitAccount(form)">
    <div class="form-content">
        <div class="form-field">
            <mat-form-field>
            <input matInput formControlName="email" placeholder="Email">
            <mat-error *ngIf="form.get('email').hasError('required')">
                E-mail is mandatory.
            </mat-error>
            <mat-error *ngIf="form.get('email').hasError('email')">
                Incorrect E-mail.
            </mat-error>
            </mat-form-field>
        </div>
        <div class="form-field">
            <mat-form-field>
            <input matInput formControlName="password" placeholder="Password" type="password">
            <mat-hint class="ac-form-field-description">Between 6 and 24 characters.</mat-hint>
            <mat-error *ngIf="form.get('password').hasError('required')">
                Password is mandatory.
            </mat-error>
            <mat-error *ngIf="form.get('password').hasError('minlength')">
                Password with less than 6 characters.
            </mat-error>
            <mat-error *ngIf="form.get('password').hasError('maxlength')">
                Password with more than 24 characters.
            </mat-error>
            </mat-form-field>
        </div>
        <div class="form-field">
            <mat-form-field>
            <input matInput formControlName="passwordAgain" placeholder="Confirm the password" type="password" [errorStateMatcher]="passwordsMatcher">
            <mat-error *ngIf="form.hasError('passwordsNotEqual')" >Passwords are different. They should be equal!</mat-error>
            </mat-form-field>
        </div>
        <div class="form-field">
            <mat-checkbox name="acceptTerms" formControlName="acceptTerms">I accept terms and conditions</mat-checkbox>
        </div>
    </div>
    <div class="form-bottom">
        <button mat-raised-button [disabled]="!form.valid">Create Account</button>
    </div>
</form>

i hope it helps!

Celso Soares
  • 617
  • 8
  • 12
7

I found a bug in AJT_82's answer. Since I do not have enough reputation to comment under AJT_82's answer, I have to post the bug and solution in this answer.

Here is the bug:

enter image description here

Solution: In the following code:

export class MyErrorStateMatcher implements ErrorStateMatcher {
  isErrorState(control: FormControl | null, form: FormGroupDirective | NgForm | null): boolean {
    const invalidCtrl = !!(control && control.invalid && control.parent.dirty);
    const invalidParent = !!(control && control.parent && control.parent.invalid && control.parent.dirty);

    return (invalidCtrl || invalidParent);
  }
}

Change control.parent.invalid to control.parent.hasError('notSame') will solve this problem.

After the small changes, the problem solved.

enter image description here

Edit: To validate the Confirm Password field only after the user starts typing you can return this instead

return ((invalidCtrl || invalidParent) && control.valid);
Henry
  • 173
  • 2
  • 10
6

I am using angular 6 and I have been searching on best way to match password and confirm password. This can also be used to match any two inputs in a form. I used Angular Directives. I have been wanting to use them

ng g d compare-validators --spec false and i will be added in your module. Below is the directive

import { Directive, Input } from '@angular/core';
import { Validator, NG_VALIDATORS, AbstractControl, ValidationErrors } from '@angular/forms';
import { Subscription } from 'rxjs';

@Directive({
  // tslint:disable-next-line:directive-selector
  selector: '[compare]',
  providers: [{ provide: NG_VALIDATORS, useExisting: CompareValidatorDirective, multi: true}]
})
export class CompareValidatorDirective implements Validator {
  // tslint:disable-next-line:no-input-rename
  @Input('compare') controlNameToCompare;

  validate(c: AbstractControl): ValidationErrors | null {
    if (c.value.length < 6 || c.value === null) {
      return null;
    }
    const controlToCompare = c.root.get(this.controlNameToCompare);

    if (controlToCompare) {
      const subscription: Subscription = controlToCompare.valueChanges.subscribe(() => {
        c.updateValueAndValidity();
        subscription.unsubscribe();
      });
    }

    return controlToCompare && controlToCompare.value !== c.value ? {'compare': true } : null;
  }

}

Now in your component

<div class="col-md-6">
              <div class="form-group">
                <label class="bmd-label-floating">Password</label>
                <input type="password" class="form-control" formControlName="usrpass" [ngClass]="{ 'is-invalid': submitAttempt && f.usrpass.errors }">
                <div *ngIf="submitAttempt && signupForm.controls['usrpass'].errors" class="invalid-feedback">
                  <div *ngIf="signupForm.controls['usrpass'].errors.required">Your password is required</div>
                  <div *ngIf="signupForm.controls['usrpass'].errors.minlength">Password must be at least 6 characters</div>
                </div>
              </div>
            </div>
            <div class="col-md-6">
              <div class="form-group">
                <label class="bmd-label-floating">Confirm Password</label>
                <input type="password" class="form-control" formControlName="confirmpass" compare = "usrpass"
                [ngClass]="{ 'is-invalid': submitAttempt && f.confirmpass.errors }">
                <div *ngIf="submitAttempt && signupForm.controls['confirmpass'].errors" class="invalid-feedback">
                  <div *ngIf="signupForm.controls['confirmpass'].errors.required">Your confirm password is required</div>
                  <div *ngIf="signupForm.controls['confirmpass'].errors.minlength">Password must be at least 6 characters</div>
                  <div *ngIf="signupForm.controls['confirmpass'].errors['compare']">Confirm password and Password dont match</div>
                </div>
              </div>
            </div>

I hope this one helps

Niclausel
  • 139
  • 1
  • 3
6

*This solution is for reactive-form

You may have heard the confirm password is known as cross-field validation. While the field level validator that we usually write can only be applied to a single field. For cross-filed validation, you probably have to write some parent level validator. For specifically the case of confirming password, I would rather do:

this.form.valueChanges.subscribe(field => {
  if (field.password !== field.confirm) {
    this.confirm.setErrors({ mismatch: true });
  } else {
    this.confirm.setErrors(null);
  }
});

And here is the template:

<mat-form-field>
      <input matInput type="password" placeholder="Password" formControlName="password">
      <mat-error *ngIf="password.hasError('required')">Required</mat-error>
</mat-form-field>
<mat-form-field>
    <input matInput type="password" placeholder="Confirm New Password" formControlName="confirm">`enter code here`
    <mat-error *ngIf="confirm.hasError('mismatch')">Password does not match the confirm password</mat-error>
</mat-form-field>
goldenbearkin
  • 496
  • 1
  • 7
  • 12
5

It's not necessary to use nested form groups and a custom ErrorStateMatcher for confirm password validation. These steps were added to facilitate coordination between the password fields, but you can do that without all the overhead.

Here is an example:

this.registrationForm = this.fb.group({
  username: ['', Validators.required],
  email: ['', [Validators.required, Validators.email]],
  password1: ['', [Validators.required, (control) => this.validatePasswords(control, 'password1') ] ],
  password2: ['', [Validators.required, (control) => this.validatePasswords(control, 'password2') ] ]
});

Note that we are passing additional context to the validatePasswords method (whether the source is password1 or password2).

  validatePasswords(control: AbstractControl, name: string) {
    if (this.registrationForm === undefined || this.password1.value === '' || this.password2.value === '') {
      return null;
    } else if (this.password1.value === this.password2.value) {
      if (name === 'password1' && this.password2.hasError('passwordMismatch')) {
        this.password1.setErrors(null);
        this.password2.updateValueAndValidity();
      } else if (name === 'password2' && this.password1.hasError('passwordMismatch')) {
        this.password2.setErrors(null);
        this.password1.updateValueAndValidity();
      }
      return null;
    } else {
      return {'passwordMismatch': { value: 'The provided passwords do not match'}};
    }  

Note here that when the passwords match, we coordinate with the other password field to have its validation updated. This will clear any stale password mismatch errors.

And for completeness sake, here are the getters that define this.password1 and this.password2.

  get password1(): AbstractControl {
    return this.registrationForm.get('password1');
  }

  get password2(): AbstractControl {
    return this.registrationForm.get('password2');
  }
The Gilbert Arenas Dagger
  • 12,071
  • 13
  • 66
  • 80
4

Just do a standard custom validator and verify first if the form itself is defined, otherwise it will throw an error that says the form is undefined, because at first it will try to run the validator before the form is constructed.

// form builder
private buildForm(): void {
    this.changePasswordForm = this.fb.group({
        currentPass: ['', Validators.required],
        newPass: ['', Validators.required],
        confirmPass: ['', [Validators.required, this.passwordMatcher.bind(this)]],
    });
}

// confirm new password validator
private passwordMatcher(control: FormControl): { [s: string]: boolean } {
    if (
        this.changePasswordForm &&
        (control.value !== this.changePasswordForm.controls.newPass.value)
    ) {
        return { passwordNotMatch: true };
    }
    return null;
}

It just checks that the new password field has the same value that the confirm password field. Is a validator specific for the confirm password field instead of the whole form.

You just have to verify that this.changePasswordForm is defined because otherwise it will throw an undefined error when the form is built.

It works just fine, without creating directives or error state matchers.

David Prieto
  • 2,239
  • 4
  • 32
  • 51
0

You can use this way to fulfill this requirement. I use the below method to validate the Password and Confirm Password.

To use this method you have to import FormGroup from @angular/forms library.

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

FormBuilder Group:

this.myForm= this.formBuilder.group({
  password    : ['', Validators.compose([Validators.required])],
  confirmPassword    : ['',  Validators.compose([Validators.required])],
},
{validator: this.checkPassword('password', 'confirmPassword') }
);

Method to Validate two fields:

 checkPassword(controlName: string, matchingControlName: string) {
    return (formGroup: FormGroup) => {
        const control = formGroup.controls[controlName];
        const matchingControl = formGroup.controls[matchingControlName];
        if (matchingControl.errors && !matchingControl.errors.mustMatch) {
            // return if another validator has already found an error on the matchingControl
            return;
        }
        // set error on matchingControl if validation fails
        if (control.value !== matchingControl.value) {
            matchingControl.setErrors({ mustMatch: true });
            this.isPasswordSame = (matchingControl.status == 'VALID') ? true : false;
        } else {
            matchingControl.setErrors(null);
            this.isPasswordSame = (matchingControl.status == 'VALID') ? true : false;
        }
    }
  }

HTML: Here I am use personalized isPasswordSame variable you can use the inbuilt hasError or any other.

<form [formGroup]="myForm">
  <ion-item>
    <ion-label position="floating">Password</ion-label>
    <ion-input required type="text" formControlName="password" placeholder="Enter Password"></ion-input>
  </ion-item>
  <ion-label *ngIf="myForm.controls.password.valid">
      <p class="error">Please enter password!!</p>
  </ion-label>
  <ion-item>
    <ion-label position="floating">Confirm Password</ion-label>
    <ion-input required type="text" formControlName="confirmPassword" placeholder="Enter Confirm Password"></ion-input>
  </ion-item>
  <ion-label *ngIf="isPasswordSame">
      <p class="error">Password and Confrim Password must be same!!</p>
  </ion-label>
</form>
Ajay Gupta
  • 2,867
  • 23
  • 28
-1

My answer is very simple>i have created password and confirm password validation using template driiven in angular 6

My html file

<div class="form-group">
  <label class="label-sm">Confirm Password</label>
  <input class="form-control" placeholder="Enter Password" type="password" #confirm_password="ngModel" [(ngModel)]="userModel.confirm_password" name="confirm_password" required (keyup)="checkPassword($event)" />
  <div *ngIf="confirm_password.errors && (confirm_password.dirty||confirm_password.touched||signup.submitted)">
  <div class="error" *ngIf="confirm_password.errors.required">Please confirm your password</div>
  </div>
  <div *ngIf="i" class='error'>Password does not match</div>
</div>

My typescript file

      public i: boolean;

      checkPassword(event) {
        const password = this.userModel.password;
        const confirm_new_password = event.target.value;

        if (password !== undefined) {
          if (confirm_new_password !== password) {
            this.i = true;
          } else {
            this.i = false;
          }
        }
      }

when clicking on submit button i check whether value of i is true or false

if true

if (this.i) {
      return false;
    }

else{
**form submitted code comes here**
}
byouness
  • 1,746
  • 2
  • 24
  • 41
-1

I did it like this. hope this will help you.

HTML :

<form [formGroup]='addAdminForm'>   
          <div class="form-group row">
            <label class="col-sm-3 col-form-label">Password</label>
            <div class="col-sm-7">
              <input type="password" class="form-control" formControlName='password' (keyup)="checkPassSame()">

              <div *ngIf="addAdminForm.controls?.password?.invalid && addAdminForm.controls?.password.touched">
                <p *ngIf="addAdminForm.controls?.password?.errors.required" class="errorMsg">*This field is required.</p>
              </div>
            </div>
          </div>

          <div class="form-group row">
            <label class="col-sm-3 col-form-label">Confirm Password</label>
            <div class="col-sm-7">
              <input type="password" class="form-control" formControlName='confPass' (keyup)="checkPassSame()">

              <div *ngIf="addAdminForm.controls?.confPass?.invalid && addAdminForm.controls?.confPass.touched">
                <p *ngIf="addAdminForm.controls?.confPass?.errors.required" class="errorMsg">*This field is required.</p>
              </div>
              <div *ngIf="passmsg != '' && !addAdminForm.controls?.confPass?.errors?.required">
                <p class="errorMsg">*{{passmsg}}</p>
              </div>  
            </div>
          </div>
      </form>

TS File :

export class AddAdminAccountsComponent implements OnInit {

  addAdminForm: FormGroup;
  password: FormControl;
  confPass: FormControl;
  passmsg: string;


  constructor(
    private http: HttpClient,
    private router: Router,
  ) { 
  }

  ngOnInit() {    
    this.createFormGroup();
  }



    // |---------------------------------------------------------------------------------------
    // |------------------------ form initialization -------------------------
    // |---------------------------------------------------------------------------------------
    createFormGroup() {    
      this.addAdminForm = new FormGroup({
        password: new FormControl('', [Validators.required]),
        confPass: new FormControl('', [Validators.required]),
      })
    }



    // |---------------------------------------------------------------------------------------
    // |------------------------ Check method for password and conf password same or not -------------------------
    // |---------------------------------------------------------------------------------------

    checkPassSame() {
      let pass = this.addAdminForm.value.password;
      let passConf = this.addAdminForm.value.confPass;
      if(pass == passConf && this.addAdminForm.valid === true) {
        this.passmsg = "";
        return false;
      }else {
        this.passmsg = "Password did not match.";
        return true;
      }
    }



}
Sushil
  • 2,324
  • 1
  • 27
  • 26