8

I have this FormGroup

defaultIdNumberValidator = [Validators.required, Validators.minLength(6),
    Validators.maxLength(11)];

this.registerForm = this.formBuilder.group({ 
  permissions: this.formBuilder.group({
    country: ['', [Validators.required]],
    identityNumber: [null, this.defaultIdNumberValidator],
  }, {validator: [this.validateId]}) 
});

and I want to clear and add validators to identityNumber depending on some conditions in this.validateId method.

validateId(input: AbstractControl) {
  if(condition) {
    input.get("identityNumber").clearValidators(); //this is working
  }
  if(condition) {
    input.get("identityNumber").setValidators(this.defaultIdNumberValidator); //not working
  }
}

When setValidators method is called I get this error (line :109 is line where setValidators is called)

ERROR TypeError: Cannot read property 'defaultIdNumberValidator' of undefined
    at RegisterComponent.validateId (register.component.ts:109)
    at eval (forms.js:742)
    at Array.map (<anonymous>)
    at _executeValidators (forms.js:742)
    at eval (forms.js:694)
    at eval (forms.js:742)
    at Array.map (<anonymous>)
    at _executeValidators (forms.js:742)
    at eval (forms.js:694)
    at eval (forms.js:742)

UPDATE:

I restart development server and now i get this error

ERROR TypeError: Cannot read property 'setValidators' of undefined
at RegisterComponent.validateId (register.component.ts:109)
at eval (forms.js:742)
at Array.map (<anonymous>)
at _executeValidators (forms.js:742)
at eval (forms.js:694)
at eval (forms.js:742)
at Array.map (<anonymous>)
at _executeValidators (forms.js:742)
at eval (forms.js:694)

UPDATE 2:

I create simple plunker to reproduce error. If you first click input and than click somewhere else you get error under it. So this error should be removed when length of input value is >= 2, and should be visible again when is >= 5. I also don't know why error disappear when length of input value is 3 and not 2...

Domen Jakofčič
  • 626
  • 1
  • 8
  • 24

1 Answers1

11

You need to bind(this) to keep the context of this. Also you need to use updateValueAndValidity for the change of the validators to be updated. There we also need to not emit an event, if you were, this would case looping until your browser crashes. So change the following:

}, {validator: this.validateId.bind(this)}) 

and the validator would look like this:

validateId(input: AbstractControl) {
  // ...
  if(...) {
    input.get("identityNumber").clearValidators();
    input.get("identityNumber").updateValueAndValidity({emitEvent:false, onlySelf:true});
  }
  if(...) {
    input.get("identityNumber").setValidators(this.defaultIdNumberValidator);
    input.get("identityNumber").updateValueAndValidity({emitEvent:false, onlySelf:true});
  }
}

Your PLUNKER

AT82
  • 71,416
  • 24
  • 140
  • 167