2

I currently have a directive that I am placing on an <input> element that will format the text to uppercase, currency, ...etc. as the user types. This all works great by implementing ControlValueAccessor, but the control validity state is not updating after the writeValue method executes.

Is there a way to force the FormControl in the ngModel on the input to validate, or is there a way to inject the NgModel/FormControl instance into a directive that is placed on the same input? Whenever I try to inject it I get a cyclic dependency error. I'm trying to use the updateValueAndValidity() method on the control property of the NgModel instance to update the state, but this could be wrong as well.

If there is also a better way to approach this then I'm open to suggestions as well. Basically trying to translate a directive from Angular 1.x that used $formatters and $parsers and required the ngModel instance...

Let me know if you would like to see snippets of code for anything specific.

DRiFTy
  • 11,269
  • 11
  • 61
  • 77
  • I think this will do what you need (possible duplicate question): http://stackoverflow.com/questions/35826325/how-to-convert-input-value-to-uppercase-in-angular-2-value-passing-to-ngcontrol – JayDM Feb 07 '17 at 14:56
  • @JayDM Thanks, actually the comment by @cghislai in @Thierry Templier's answer mentioned something about having to call `onTouched` to get validation to work so I tried it and that did it. I just added a call to `onTouched` prior to calling `onChange` and the validation state is updating fine. – DRiFTy Feb 07 '17 at 15:06

2 Answers2

1

Sounds like updateValueAndValidity is what you want.
Angular 2 AbstractControl class, which is the super for FormControl, has this method which will force the check of validity state on the control.

You could be accessing the specific formControl in a way that angular doesn't like. For reference, I have an overarching 'form' of type formGroup, a contained 'controlGroup' of type formGroup, and a specific 'control' of type formControl. I access its methods via form.controls['controlGroup'].controls.['control'].<method>

j.k
  • 413
  • 1
  • 7
  • 14
  • Yeah that's what I was thinking as well. I wasn't able to get this functionality working by extending `AbstractControl` or even `NgControl`... I had to implement `ControlValueAccessor` and try to get a reference to `NgControl` or the base `FormControl` somehow but was unsuccessful. In my case just calling `onTouched` when the `(input)` host event binding runs, it started updating the validation state. Angular must be only running that code when that touched event runs. – DRiFTy Feb 07 '17 at 16:11
  • I see; sorry I had glossed over that part of your question. Your scenario is slightly different from what I have, but I would have expected it to work the same. We have a subscription to value changes on a formControl1 upon which another formControl2 depends. When I see a value change on formControl1, I complete some actions with formControl2 and then have to force a check of its validity state with updateValueAndValidity. – j.k Feb 07 '17 at 17:03
0

For anyone implementing a directive using ControlValueAccessor and having this same issue, I was able to get the validation state to update by calling the onTouched() method (the method that is set via the registerOnTouched() method) during the writeValue() method.

My directive updates the ElementRef.nativeElement.value property in writeValue() and then calls onChange() and onTouched() to get the value to propagate to the model, as well as update the validation state.

DRiFTy
  • 11,269
  • 11
  • 61
  • 77