Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Confirm password validation in Angular 6 [duplicate]

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.

like image 214
Shankar Avatar asked Jul 31 '18 05:07

Shankar


3 Answers

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

like image 97
AT82 Avatar answered Oct 17 '22 04:10

AT82


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>
like image 59
Alok Mali Avatar answered Oct 17 '22 04:10

Alok Mali


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.

like image 36
Zahema Avatar answered Oct 17 '22 02:10

Zahema