0

I have a custom control/component which I hook an async validator to in the ReactiveForms style e.g.

this.myform = new FormGroup({
  mycontrol : new FormControl('', [], this.myvalidator.bind(this)),

If I break on the myvalidator function, I can see that it's called multiple times, the main times being on "new FormControl" and then again when the control is assigned a value.

By hard coding the response from the validation to something like:

return of({ error: 'done broke...'});

The control receives the error in its "errors" object and the UI shows the "ng-invalid" class. All good..

I actually need my validator to know what control we're validating, in order to get the correct response from the service. To do this I have some method named "getControlName(control)" which uses the control.parent to find the name of the current control (clunky but works for now).

Problem is! on instantiation of FormControl where we pass in the validator, that actually seems to trigger the myvalidator function, at which point the control.parent is undefined. So I simply add a check for control.parent and return of(null) when there isn't one... except that this doesn't work.

If the validator function looks like this:

testVal(control: AbstractControl): Observable<{}> {
  if (!control.parent) { 
    return of(null); 
  } else {
    return of({ error: 'there is a parent this time' });
  }

Then I get an error on the errors object of my control and the ng-invalid is set on the class list. Great!

But if my method looks more like this:

  testVal(control: AbstractControl): Observable<{}> {
  if (!control.parent) { return of(null); }

    const field = this.getControlName(control);
    const r = this.myservice.validate(field).
... service stuff ...
    return r; // this is the Observable from my service method

}

Then I get an error on my errors object, but the ng-valid class is still there!

Why the difference, and what am I doing wrong here?

Thanks :)

10
  • Why do you bind(this) ?! Commented Jan 15, 2019 at 13:34
  • Your custom validator function should return : null (if the control is valid) or an object such as { validatorProperty: { value: control.value } } (if the control is invalid) Commented Jan 15, 2019 at 13:36
  • @Florian I believe I can use bind(this) and then get access to functions in my component, or alternatively pass in the validator function (e.g. new FormControl('', [], this.myvalidator) ... ), and then define myvalidator as an arrow function. Either way I get the same thing Commented Jan 15, 2019 at 13:43
  • @Florian the issue here is that 1) the control has no parent on the first time it's called, so i have to return something, 2) when i return null (valid) when there's no parent, and then an error when there is a parent (as a test) then this works! but as soon as the validator goes off to the service it half validates it. It adds an error to errors but leaves ng-valid in place. Commented Jan 15, 2019 at 13:46
  • I'm sorry I'm not sure I understand properly... Could you create a stackblitz and I try to figure out what you mean ? Commented Jan 15, 2019 at 14:17

0

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.