5

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; 
  }
Akber Iqbal
  • 14,487
  • 12
  • 48
  • 70
swagath
  • 125
  • 1
  • 3
  • 10
  • please refer https://stackoverflow.com/questions/51605737/confirm-password-validation-in-angular-6/52797413#52797413 – Ajay Ojha Dec 11 '18 at 08:15

5 Answers5

9

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

DeborahK
  • 57,520
  • 12
  • 104
  • 129
  • 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. – Ajay Ojha Dec 11 '18 at 08:09
  • 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. – DeborahK Dec 11 '18 at 08:10
  • 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. – Ajay Ojha Dec 11 '18 at 08:22
  • 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. – DeborahK Dec 11 '18 at 17:06
  • 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. – Ajay Ojha Dec 11 '18 at 18:17
  • 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. :-) – DeborahK Dec 11 '18 at 19:11
  • 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 Dec 12 '18 at 04:41
  • 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 : https://www.rxweb.io/form-validations/compare/validators and looking for suggestions to make it better. – Ajay Ojha Dec 15 '18 at 12:42
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>
Krishnadas PC
  • 5,981
  • 2
  • 53
  • 54
2

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 }
}
R. Viral
  • 386
  • 1
  • 6
1

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
        }
    }
}
swagath
  • 125
  • 1
  • 3
  • 10
-9

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>
Paresh Gami
  • 4,777
  • 5
  • 23
  • 41