Yehuda Menahem
Yehuda Menahem

Reputation: 385

Angular 4 - validator custom function this is undefined

I'm building an app with component FormComponent. inside I'm using reactive forms module from angular core and create a custom validator. the function is calling another function by using this - as I supposed it will refer to the FormComponent, but it refers to be 'undefined' (?)

The code in onInit defines the FormGroup and FormControl and outside of it defines the functions

import { Component, OnInit } from '@angular/core';
import { FormGroup, FormControl, Validators } from '@angular/forms';
import { Router } from '@angular/router';
import { HttpClient } from '@angular/common/http';

@Component({
  selector: 'app-form',
  templateUrl: './form.component.html',
  styleUrls: ['./form.component.css']
})
export class FormComponent implements OnInit {

  formInsurance:FormGroup;
  private id:FormControl;


  constructor(){}


  ngOnInit() {

    this.id = new FormControl('',[
      Validators.required,
      Validators.minLength(3),
      Validators.maxLength(10),
      Validators.pattern('^[0-9]+(-[0-9]+)+$|^[0-9]+$'),
      this.foo
    ]);


    this.formInsurance = new FormGroup({
      id:this.id      
    })


  }


  foo(control:FormControl){
  this.boo();
  if(control.value){
    return {
      objToReturn: {
          returned: name
      }
    };
  }
  return null
}

boo(){
  console.log('boo')

}

}

Upvotes: 18

Views: 10594

Answers (3)

Rstar37
Rstar37

Reputation: 534

You can return the needed function, take what you want from this as a parameter and return the function that you want. That way it's cleaner because often times you'd only need one value from this

in you example, it would look like this:

import { Component, OnInit } from '@angular/core';
import { FormGroup, FormControl, Validators } from '@angular/forms';
import { Router } from '@angular/router';
import { HttpClient } from '@angular/common/http';

@Component({
  selector: 'app-form',
  templateUrl: './form.component.html',
  styleUrls: ['./form.component.css']
})
export class FormComponent implements OnInit {

  formInsurance: FormGroup;
  private id: FormControl;


  constructor() { }

  ngOnInit() {

    this.id = new FormControl('', [
      Validators.required,
      Validators.minLength(3),
      Validators.maxLength(10),
      Validators.pattern('^[0-9]+(-[0-9]+)+$|^[0-9]+$'),
      this.foo(this.boo)
    ]);


    this.formInsurance = new FormGroup({
      id: this.id
    })
  }

  foo(boo) {
    return (control: FormControl) => {
      boo();
      if (control.value) {
        return {
          objToReturn: {
            returned: name
          }
        };
      }
      return null
    }
  }

  boo() {
    console.log('boo')
  }

Upvotes: 0

Greg
Greg

Reputation: 776

And of course, the other alternative is the arrow function, which auto-binds to the this context:

import { Component, OnInit } from '@angular/core';
import { FormGroup, FormControl, Validators, ValidationErrors } from '@angular/forms';
import { Router } from '@angular/router';
import { HttpClient } from '@angular/common/http';

@Component({
  selector: 'app-form',
  templateUrl: './form.component.html',
  styleUrls: ['./form.component.css']
})
export class FormComponent implements OnInit {

  formInsurance:FormGroup;
  private id:FormControl;

  constructor() {}

  ngOnInit() {
    this.id = new FormControl('',[
      Validators.required,
      Validators.minLength(3),
      Validators.maxLength(10),
      Validators.pattern('^[0-9]+(-[0-9]+)+$|^[0-9]+$'),
      this.foo
    ]);

    this.formInsurance = new FormGroup({
      id:this.id      
    })
  }

  foo = (control: FormControl): ValidationErrors => {
    this.boo();
    if (control.value) {
      return {
        objToReturn: {
          returned: name
        }
      };
    }
    return null
  }

  boo() {
    console.log('boo')
  }
}

Upvotes: 12

Gorka Hernandez
Gorka Hernandez

Reputation: 3958

The context in the foo method when called from within the FormControl is not referencing the FormComponent.

You can do the following to fix this behavior using bind to set the context yourself:

import { Component, OnInit } from '@angular/core';
import { FormGroup, FormControl, Validators } from '@angular/forms';
import { Router } from '@angular/router';
import { HttpClient } from '@angular/common/http';

@Component({
  selector: 'app-form',
  templateUrl: './form.component.html',
  styleUrls: ['./form.component.css']
})
export class FormComponent implements OnInit {

  formInsurance:FormGroup;
  private id:FormControl;


  constructor(){}


  ngOnInit() {

    const id = new FormControl('',[
      Validators.required,
      Validators.minLength(3),
      Validators.maxLength(10),
      Validators.pattern('^[0-9]+(-[0-9]+)+$|^[0-9]+$'),
      this.foo.bind(this)
    ]);

    this.id = id;

    this.formInsurance = new FormGroup({
      id
    })
  }


  foo(control:FormControl) {
    this.boo();
    if(control.value){
        return {
          objToReturn: {
              returned: name
          }
        };
      }
    return null
  }

  boo(){
    console.log('boo')

  }
}

Upvotes: 30

Related Questions