Gabriel Costin
Gabriel Costin

Reputation: 122

Cannot read property of undefined Reactive Forms

I am trying to make a custom validator for password but I don't get why I get the following error ERROR TypeError: Cannot read property 'f' of undefined

Below is my code:

registerForm: FormGroup;
submitted = false;
constructor(private Auth:AuthService, private router:Router,private 
formBuilder:FormBuilder) { }

ngOnInit() {
this.registerForm = this.formBuilder.group({
  userName: ['', Validators.compose([Validators.required,Validators.minLength(6),Validators.maxLength(30),Validators.pattern('^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+.[a-zA-Z0-9-.]+$')])],
  email: ['', Validators.compose([Validators.required, Validators.email])],
  password: ['', Validators.compose([Validators.required, Validators.minLength(6)])],
  cpassword: ['', Validators.required,passwordMatch()] //paswordMatch triggers the error
},);
}

get f() { return this.registerForm.controls; }

function  passwordMatch() { 
if(this.f != undefined){
let passwordInput = this.f.password,
   passwordConfirmationInput = this.f.cpassword;
if (passwordInput.value !== passwordConfirmationInput.value) {
 return passwordConfirmationInput.setErrors({notequal: true})
}
else {
   return passwordConfirmationInput.setErrors(null);
}
}
}

Upvotes: 1

Views: 2826

Answers (2)

AVJT82
AVJT82

Reputation: 73337

this is undefined in your function, therefore you cannot reference it.

What I would add a sub formgroup, that would track both the value of password and confirm password, but if you want to go this route, modify your code as such:

// ...
// see the brackets also around the validators! No need to use Validators.compose
cpassword: ['', [Validators.required, passwordMatch]]
// ...

Then you would access the form group with parent. Also you need to return either null (valid) or an error:

function passwordMatch(input: FormControl) {
  if (input.parent) {
    let passwordInput = input.parent.get('password');
    if (passwordInput.value !== input.value) {
      return { notequal: true }
    }
    else {
      return null;
    }
  }
}

DEMO: StackBlitz

But with this, we need to remember, if user modifies password field after modifying the confirmpassword and the passwords do not match, the form will still be considered valid. Here's a way to avoid this: password and confirm password field validation angular2 reactive forms

Upvotes: 1

Fateh Mohamed
Fateh Mohamed

Reputation: 21357

you can use input .root to get access to the parent of a control (your registerForm) try this, no need for f function

 function  passwordMatch(input: FormControl) { 
  if(input.root != undefined){
  let passwordInput = input.root.controls.password,
  passwordConfirmationInput = input.root.controls.cpassword;
  if (passwordInput.value !== passwordConfirmationInput.value) {
   return passwordConfirmationInput.setErrors({notequal: true})
  }
  else {
    return passwordConfirmationInput.setErrors(null);
  }
 }

...

cpassword: ['', Validators.required, passwordMatch]

Upvotes: 0

Related Questions