-1

I am trying To create custom Validation to match password and ConfirmPassword.

But I am getting the error.

I am new to angular. Please ignore my ignorance.

Is it a good idea to create custom validation to match password and Confirm password? or is there a better way out?

Here is the code. Please help

import { Component, OnInit } from '@angular/core';
import { FormGroup, FormControl, Validators, AbstractControl, ValidatorFn, ValidationErrors, FormBuilder } from '@angular/forms';


@Component({
  selector: 'app-sample-form',
  templateUrl: './sample-form.component.html',
  styleUrls: ['./sample-form.component.scss']
})
export class SampleFormComponent implements OnInit {
  formattedMessage: string;
  passMatch: Boolean;
  formValid: boolean;
  constructor() { }

  ngOnInit() {
    this.onChanges();
  }


  sample: FormGroup = new FormGroup({
    inpt: new FormControl(null, Validators.required),
    pass: new FormControl("", Validators.required),
    cpass: new FormControl("", [Validators.required, this.passwordMatch]),
    iagree: new FormControl(null, Validators.nullValidator)
  });

  onChanges(): void {
    this.sample.valueChanges.subscribe(val => {
      console.log("======================================");
      console.log("PASS  : " + this.sample.controls.pass.value);
      console.log("CPASS  : " + this.sample.controls.cpass.value);
      if (this.sample.controls.pass.value == this.sample.controls.cpass.value) {
        this.passMatch = true;
        console.log("MATCHED");
      } else {
        this.passMatch = false;
        console.log("MIS-MATCHED");
      }

      this.formValid = this.sample.valid;
      console.log("PASS MATCH : " + String(this.passMatch));
      console.log("FORM VALID : " + String(this.formValid));


    });
  }

  passwordMatch(group: FormGroup): ValidationErrors | null {
    let pass = group.controls.pass.value;
    let confirmPass = group.controls.cpass.value;

    return pass === confirmPass ? null : { notSame: true }
  }

  sumbit() {

  }

}

I am Getting this error :

ERROR Error: Uncaught (in promise): TypeError: Cannot read property 'pass' of undefined
TypeError: Cannot read property 'pass' of undefined
    at passwordMatch (sample-form.component.ts:51)
    at forms.js:1480
    at Array.map (<anonymous>)
    at _executeValidators (forms.js:1476)
    at FormControl.validator (forms.js:1418)
    at FormControl._runValidator (forms.js:4089)
    at FormControl.updateValueAndValidity (forms.js:4050)
    at new FormControl (forms.js:4656)
    at new SampleFormComponent (sample-form.component.ts:25)
    at createClass (core.js:31985)
    at resolvePromise (zone-evergreen.js:797)
    at resolvePromise (zone-evergreen.js:754)
    at zone-evergreen.js:858
    at ZoneDelegate.invokeTask (zone-evergreen.js:391)
    at Object.onInvokeTask (core.js:39680)
    at ZoneDelegate.invokeTask (zone-evergreen.js:390)
    at Zone.runTask (zone-evergreen.js:168)
    at drainMicroTaskQueue (zone-evergreen.js:559)

-Ashish

Ashish
  • 479
  • 3
  • 7
  • 18
  • `this.sample.controls` isn't set anywhere, so it's `undefined`, and you can't access property `.pass` of `undefined`. You're setting `group.controls.pass`, but not `this.sample.controls.pass` – Tim Lewis Nov 11 '19 at 16:12
  • Possible duplicate of [JavaScript "cannot read property "bar" of undefined](https://stackoverflow.com/questions/8004617/javascript-cannot-read-property-bar-of-undefined) – Liam Nov 11 '19 at 16:13
  • check this https://angular.io/guide/form-validation#custom-validators for building custom validators. – hawks Nov 11 '19 at 16:15
  • Hi Tim , I have tried "group.controls.pass". But the error is still there ``` passwordMatch(group: FormGroup): ValidationErrors | null { let pass = group.controls.pass; let confirmPass = group.controls.cpass; return pass === confirmPass ? null : { notSame: true } } ``` I am getting the same error : – Ashish Nov 11 '19 at 16:22

3 Answers3

0

You need to bind the passwordMatch function because angular will call it in different context

try

    cpass: new FormControl("", [Validators.required, this.passwordMatch.bind(this)]),

instead of

    cpass: new FormControl("", [Validators.required, this.passwordMatch]),

Updated answer:

You need to do both bind the passwordMatch method and add pass and cpass in the separate form group with generic validator something like this:

    sample = new FormGroup({
      inpt: new FormControl(null, Validators.required),
      iagree: new FormControl(null, Validators.nullValidator),

      confirmPasswordForm: new FormGroup({
        pass: new FormControl('', Validators.required),
        cpass: new FormControl('', Validators.required),
      }, {
        validator: this.passwordMatch.bind(this),
      })
    });

But you need create nested form in you html

  • In custom Validation, By default, Form Controll is passed as Paramater to the custom validation function. If I do : passwordMatch(group: FormGroup): ValidationErrors | null { console.log("FUNC : " + group.value); return null; } I notice thet Confirm Password value is printed. But the challange is to get the valie of Password also. Since the control does not have the Value of "password" – Ashish Nov 11 '19 at 16:56
0

You are assigning your validator to the formControl cpass, so the formControl you will get through the arguments is only cpass. That validator needs the parent level to be able to access both controls (pass and cpass). Try this instead:

sample: FormGroup = new FormGroup({
  inpt: new FormControl(null, Validators.required),
  pass: new FormControl("", Validators.required),
  cpass: new FormControl("", [Validators.required]),
  iagree: new FormControl(null, Validators.nullValidator)
}, {validators: [this.passwordMatch]});

That should do the trick. The error will be in sample formgroup, not in the formControl, which in my opinion makes sense because it affects to more than one form controls.

David G.
  • 1,255
  • 9
  • 16
0

This actually solved the problem. to use the keyword "root"

passwordMatch(control: AbstractControl): ValidationErrors | null {
    const pass = control.root.get('pass');
    const cpass = control.root.get('cpass');

    if (pass != null && cpass != null) {
      console.log("Pass : ", pass.value);
      console.log("cpass : ", cpass.value);
      if (pass.value != cpass.value) {
        console.log("MISMATCH");
        return { PasswordMismatch: 'Password Mismatch' }
      } else {
        console.log("MATCH");
        return null;
      }
    } else {
      console.log("MISMATCH2");
      return { PasswordMismatch: 'Password Mismatch' };
    }
  }
Ashish
  • 479
  • 3
  • 7
  • 18