password and confirmpassword validation in angular using reactive forms

22,550

Solution 1

You can check form value of both like below.

<div class="error-msg" *ngIf="registerForm3.value.password !== registerForm3.value.confirmpassword">
    Passwords don't match.
</div>

Solution 2

I didn't think that you could use a component member function (method) for your custom validator. I assumed it needed to be a function external from your class.

Mine looks like this:

function emailMatcher(c: AbstractControl): { [key: string]: boolean } | null {
  const emailControl = c.get('email');
  const confirmControl = c.get('confirmEmail');

  if (emailControl.pristine || confirmControl.pristine) {
    return null;
  }

  if (emailControl.value === confirmControl.value) {
    return null;
  }
  return { 'match': true };
}

And I attach the validator to a child formGroup like so:

this.customerForm = this.fb.group({
  firstName: ['', [Validators.required, Validators.minLength(3)]],
  lastName: ['', [Validators.required, Validators.maxLength(50)]],
  emailGroup: this.fb.group({
    email: ['', [Validators.required, Validators.email]],
    confirmEmail: ['', Validators.required],
  }, { validator: emailMatcher }),
  phone: ''
});

You could put your validator in a separate file, or in the same file either above or below your component class. Something like this:

function passwordMatchValidator(frm: FormGroup) {
  return frm.controls['password'].value === 
frm.controls['confirmpassword'].value ? null : {'mismatch': true};
}

Then you would define the validator without the this keyword:

{validator: passwordMatchValidator},

You can find the complete example here: https://github.com/DeborahK/Angular-ReactiveForms/tree/master/Demo-Final

Solution 3

For angular 8 you can use a custom validation like this.

Import the required libraries

import { FormGroup, FormControl, Validators, ValidatorFn, ValidationErrors } from '@angular/forms';


const passwordErrorValidator: ValidatorFn = (control: FormGroup): ValidationErrors | null => {
  const password = control.get('a');
  const repeatPassword = control.get('b');
  return password.value != repeatPassword.value ? { 'passwordError': true } : null;
};

Init form like this

 heroForm = new FormGroup({   
    'a': new FormControl(),
    'b': new FormControl()
  }, { validators: passwordErrorValidator });

And in component

 <form [formGroup]="heroForm" (ngSubmit) ="createUser(heroForm.value)">
                <input id="a" name="a" class="form-control"
                required minlength="4"
                formControlName="a">
                <input id="b" name="b" class="form-control"
                required minlength="4"
                formControlName="b" >
                 <div *ngIf="heroForm.errors?.passwordError && (heroForm.touched || heroForm.dirty)" class="cross-validation-error-message alert alert-danger">
                  password mismatch
              </div>
              <input type="submit" class="btn btn-primary" value="Submit" />
            </form>

Solution 4

You can try this its working for me...

In your form

this.passwordForm = this.fb.group({
        newPassword: ['', [Validators.required, Validators.minLength(6)]],
        confirmNewPassword: ['', [Validators.required, Validators.minLength(6), (control => ValidationService.confirmPassword(control, this.passwordForm, 'newPassword'))]]
    });

ValidationService file

static confirmPassword(control: FormControl, group: FormGroup, matchPassword: string) {
    if (!control.value || group.controls[matchPassword].value !== null || group.controls[matchPassword].value === control.value) {
        return null;
    }
    return { 'mismatch': true }
}

Solution 5

finally i found my solution

export class ConfirmPasswordValidator {
    static MatchPassword(control: AbstractControl) {
       let password = control.get('password').value;

       let confirmpassword = control.get('confirmpassword').value;

        if(password != confirmpassword) {
            control.get('confirmpassword').setErrors( {ConfirmPassword: true} );
        } else {
            return null
        }
    }
}
Share:
22,550
swagath
Author by

swagath

Updated on June 16, 2020

Comments

  • swagath
    swagath almost 4 years

    i have attached my code below .im facing problem in adding password mismatch validation.im not getting validation error if i type mismatching password

    register.component.html

    <div class="form-group row mt-3">
     <label class="col-md-4 col-lg-4 text-center">UserName:<span style="color:red">*</span></label>
    <input kendoTextBox required type="text" class="  col-md-6 col-lg-6 form-control " placeholder="Enter Your UserName " formControlName="username"/>
      <div *ngIf="(submitted||f2.username.touched) && f2.username.invalid" class="error-msg">
     <div *ngIf="f2.username.errors.required">UserName  is required</div>
     </div> </div>
     <div class="form-group row">
    <label class="col-md-4 col-lg-4 text-center">Password:<span style="color:red">*</span></label>
    <input kendoTextBox type="password" required  class="  col-md-6 col-lg-6 form-control " placeholder="Enter Your passowrd " formControlName="password"/>
    
     <div *ngIf="(submitted||f2.password.touched) && f2.password.invalid" class="error-msg">
    <div *ngIf="f2.password.errors.required">password  is required</div>
    <div *ngIf="f2.password.errors.minlength">minimum of 6 characters required</div>
        </div>
    </div>
    <div class="form-group row">
       <label class="col-md-4 col-lg-4 text-center">ConfirmPassword:
    <span style="color:red">*</span></label>
    <input kendoTextBox required type="password" class="  col-md-6 col-lg-6 form-control " placeholder="Enter Your new password " formControlName="confirmpassword"/>
     <div *ngIf="(submitted||f2.confirmpassword.touched) && f2.confirmpassword.invalid" class="error-msg">
     <div *ngIf="f2.confirmpassword.errors.required"> confirm password  is required</div>  <div *ngIf="f2.confirmpassword.errors.minlength">minimum of 6 characters required
    </div>
    <div class="error-msg" *ngIf="f2.errors?.mismatch && (f2.controls['confirmpassword'].required || f2.controls['confirmpassword'].touched)">
                                  Passwords don't match.
    </div>
                              </div>
                          </div>
        enter code here
    

    registercomponent.ts file

    here i have used formBuilder.other things are working fine ,only validation for mismatching not working

     this.registerForm3 = this.formBuilder.group({
        username:['', Validators.required],
        password: ['', [Validators.required, Validators.minLength(6)]],
        confirmpassword:['', [Validators.required, Validators.minLength(6)]],
      },
      {validator: this.passwordMatchValidator},
      );
    
    passwordMatchValidator(frm: FormGroup) {
    eturn frm.controls['password'].value === 
    frm.controls['confirmpassword'].value ? null : {'mismatch': true};
        }
     get f2() { 
        return this.registerForm3.controls; 
      }
    
  • Ajay Ojha
    Ajay Ojha over 5 years
    Just for my knowledge, is this is a right practice to put a validator on FormGroup level? As per my understanding, if there are many fields then it will create a performance issue. Because this will call every time, Please share your thoughts on alternates.
  • DeborahK
    DeborahK over 5 years
    Personally, I create a new form group with only the two elements to validate and then attach the validator there. I'll update my answer with a link to the full code.
  • Ajay Ojha
    Ajay Ojha over 5 years
    Based on your updated answer: One more new question arise. Say for example: In my form there are many fields which needs to be validate based on some other FormControl Values, Then Do I need to create seperate FormGroup for cross field validation of FormControl. Don't you think the code become clumsy, if I create a seperate FormGroup? Please let me know your views.
  • DeborahK
    DeborahK over 5 years
    These types of decisions are impacted by so many factors, it is hard to say at which point it makes sense just to validate the entire form's group. Build it the way it makes sense and then look at whether there are performance issues you need to work on.
  • Ajay Ojha
    Ajay Ojha over 5 years
    Now performance is not the issue based on your updated answer, but my question was: Is this is the right practice to create a separate FormGroup for every Cross-Field Validation? Don't you think the code become clumsy with your updated answer? Please share your inputs on respective questions. I am just curious about what are the other good alternatives to overcome this kind of problems.
  • DeborahK
    DeborahK over 5 years
    My input is that it is hard to say at which point it makes sense just to validate the entire form's group. I have always created separate forms groups, but my validation needs have been simple and I've only had one or two cross-field validations per form on the code I've worked on. Your mileage may vary. :-)
  • Ajay Ojha
    Ajay Ojha over 5 years
    Thanks for the response, But it is very basic need in enterprise applications advanced forms of cross-field validation more than two fields, But anyways you have the only experience on two cross-field validation. :-)
  • Ajay Ojha
    Ajay Ojha over 5 years
    I didn't mean to offend you, as english is not my first language. I meant to say that you might have not came across more than two fields cross field validation. I have been building something similar to I was curios to verify my approach from someone experienced like you. Here is the link of compare password : rxweb.io/form-validations/compare/validators and looking for suggestions to make it better.
  • Devang Mistry
    Devang Mistry almost 5 years
    This is not good practice. it will allow you to submit form even if password and confirm password are not matched.
  • Paresh Gami
    Paresh Gami almost 5 years
    @DevangMistry Then How do like you implement that?