Passing custom parameters in custom validator


#1

Dear Ionites

I started experimenting with FormBuilder and custom validators.

I want to be able to pass one or more parameters to my custom validator from other parts of the form.

For example:

  1. Have 2 controls
    Password
    PasswordConfirm

My ‘Password’ validation is straightforward
But my PasswordConfirm validation is that it must be equal to Password value.
How I can pass the ‘Password’ value to my custom validator for PasswordConfirm control?

I googled a bit but I did not find something straightforward.
Is this possible? Is my approach correct?

Thank you


#2

Here’s how I do this:

class MyPage {
  form: ControlGroup;

  constructor(fb: FormBuilder) {
    this.form = fb.group({
      // other fields
      'pwd1': ['', Validators.required],
      'pwd2': ['', Validators.required]
    }, {validator: MyPage.passwordsMatch});
  }

  static passwordsMatch(cg: ControlGroup): {[err: string]: any} {
    let pwd1 = cg.controls['pwd1'];
    let pwd2 = cg.controls['pwd2'];
    let rv: any = {};
    if ((pwd1.touched || pwd2.touched) && pwd1.value !== pwd2.value) {
      rv.passwordMismatch = true;
    }
    return rv;
  }
}

#3

Thanks!
It’s an eye opener :slight_smile:


#4

Hmm. Thanks rapropos
Indeed your method works, and it’s good for the form validation as a whole.

But in my case I would like to validate the pwd2 itself while it is updated itself.

Because the UI displays the input differently while it is not valid. But for validation I need the value of pwd1 and I can’t seem to pass it or capture it from within my control validation. Any ideas how to approach this?

Thank you in advance.


#5

To do exactly as you’re describing, you would probably have to make the validator a lambda that captures pwd1, something like this:

let validator = () => {
  this.form.controls['pwd1'] should be accessible here
};

this.form.controls['pwd2'].validator = validator;

However, that’s sort of ugly. If all you really need is to have the error be applied to pwd2 instead of a larger unit, you can still use the ControlGroup validator strategy in my first post, and just apply the error directly to the pwd2 control.

pwd2.setErrors({'passwordMismatch':true});

I find that cleaner.


How to validate multiple Angular 2+/Ionic2+ form controls using one asynchronous function on submit?
#6

Many thanks :slight_smile:


#7

Hi,

I have multiple validators for password, I have created custom validator “PasswordValidator” to compare two passwords.
Another validator is required field and password pattern.
It’s looks like this.

this.userConfirmPwdForm = formBuilder.group({
    newPassword: new FormControl('', Validators.compose([Validators.pattern('((?=.*\\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[!*@#$%]).{12,99})'), Validators.required])),
    confirmPassword: new FormControl('', Validators.compose([Validators.pattern('((?=.*\\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[!*@#$%]).{12,99})'), Validators.required]))      
}, {validator: PasswordValidator.isMatching});

This is my PasswordValidator

static isMatching(builder: FormGroup): any  {
        console.log("password check");
        let pwd1 = builder.controls['newPassword'];
        let pwd2 = builder.controls['confirmPassword'];
        console.log("newPassword Name : " + pwd1.value);
        console.log("confirmPassword Name : " + pwd2.value);
        let rv: any = {};
        if ((pwd1.touched || pwd2.touched) && pwd1.value != pwd2.value) {
            console.log("password not match");             
            return {
                "valid": false
            };
        }
        else    {
            console.log("password match");
            return {
                "valid": true
            };
        }
    }

I am tring to show in error based on password validation.

<ion-item *ngIf="!userConfirmPwdForm.controls.confirmPassword.valid  && (userConfirmPwdForm.controls.confirmPassword.dirty || submitAttempt)">
  <p class="ion-error-label-placeholder">Password should have Uppercase letter,<br>lowercase letter, number and special character</p>
</ion-item>
<ion-item *ngIf="!userConfirmPwdForm.controls.valid  && (userConfirmPwdForm.controls.dirty || submitAttempt)">
  <p class="ion-error-label-placeholder">Password and confirm password<br>do not match</p>
</ion-item>    

Currently, It’s validating pattern and shows in UI(with HTML tags), I have put logs in PasswordValidator, It’s validating in logs. Somehow Password validator is not reflecting in UI, It’s not showing error information.

Is there anyway to display error with custom validator?


#8

the log password match is appear?