2

I got a custom validator that expects a string parameter. However when i change the parameter in code that doesn't change an initial value that was passed during form initialization. The only workaround I found is to remove validator and add it again with new parameter.

Is it a desired behaviour? How can i force angular to "reload" validator parameter?

Demo of unwanted behaviour.

Code:

HTML

<form [formGroup]="reactiveForm">
    <input type="text" formControlName="input">
  <button (click)="changeToB()" >switch to b</button>
<br>
  valid: {{reactiveForm.get('input').valid}}
  <br>
  shouldBeEqualTo: {{shouldBeEqualTo}}
</form>

TS

export class AppComponent {
  shouldBeEqualTo = 'a';
  reactiveForm: FormGroup;
  constructor(private fb: FormBuilder) {
    this.reactiveForm = this.fb.group({input: ['a', customValidator(this.shouldBeEqualTo)]})
  }

  changeToB(){
    this.shouldBeEqualTo = 'b';
  }
}

export function customValidator(equalTo: string): ValidatorFn{
 return (c: AbstractControl): { [key: string]: any } => {
   console.log(equalTo)
   console.log(c.value)
   if(c.value !== equalTo){
     return {valid: false};
   }
   return null;
 }
}

1 Answer 1

2

You may need to add custome validator to form instead of the form control this way you can have access to local property.

component

  shouldBeEqualTo = 'a';
  reactiveForm: FormGroup;
  constructor(private fb: FormBuilder) {
    this.reactiveForm = this.fb.group({ input: ['a' ]},
                      {validator:this.getCustomeValidator()})
  }

  changeToB() {
    this.shouldBeEqualTo = 'b';
  }

  getCustomeValidator() {
    return (c: AbstractControl): { [key: string]: any } => {
      if (c.value !== this.shouldBeEqualTo) {
        return { valid: false };
      }
      return null;
    }
  }
}

demo

Another way may consider can make the validator reusable,but I still recommand first solution

export class AppComponent {
  shouldBeEqualTo = 'a';
  reactiveForm: FormGroup;
  constructor(private fb: FormBuilder) {
    this.reactiveForm = this.fb.group({input: ['a', customValidator(this,'shouldBeEqualTo')]})
  }

  changeToB(){
    this.shouldBeEqualTo = 'b';
  }
}

export function customValidator($this,property:string): ValidatorFn{
 return (c: AbstractControl): { [key: string]: any } => {
   if(c.value !== $this[property]){
     return {valid: false};
   }
   return null;
 }
}

demo

Sign up to request clarification or add additional context in comments.

4 Comments

This way i lost a validator reusability in other forms. It also feels hacky doesn't it?
Your validator depend on other value that may going to update like class property if 's will not be possible in that case you make the validator not reusable :\
it is working. However i'd wait to mark question as answered. Maybe i will figure out how to extract validator to make it reusable across components. Thank you anyway.
I have add another solution @karoluS

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.