Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to setValidators to FormGroup after its initialization

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...

like image 720
Domen Jakofčič Avatar asked Dec 18 '17 11:12

Domen Jakofčič


1 Answers

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

like image 174
AT82 Avatar answered Oct 17 '22 22:10

AT82