I want to format specific input fields when the form is first updated by the initial response, but I can't figure out how to do the initial formatting.
The example below is one attempt where I tried to listen to ngModelChange. This creates an infinite loop if you setValue on the FormControl or the input won't take values, but it gets the idea across that I'd like to update the formatting after the initial response is received by the parent component. Below that is how I handle formatting afterwards using user events, which works.
import { Directive, HostListener, ElementRef } from '@angular/core';
import { DecimalPipe } from '@angular/common';
import { FormGroup, NgControl } from '@angular/forms';
@Directive({
selector: '[cfFloat]',
providers: [DecimalPipe]
})
export class FloatDirective {
public element: HTMLInputElement;
constructor(
private elementRef: ElementRef,
private decimalPipe: DecimalPipe,
private ngControl: NgControl
) {
this.element = this.elementRef.nativeElement;
}
// ISSUE: this is not the proper event to listen to for a single
// initial formatting of any field with this directive, but I
// can't figure out how you would do the equivalent to this???
@HostListener('ngModelChange', ['$event'])
onModelChange(event: Event) {
let value = this.element.value.replace(/[^\d\.]+/g, '');
value = this.decimalPipe.transform(value, '1.2-2');
//this.ngControl.control.setValue(value); // infinite loop, blows stack
this.element.value = value; // prevents changes from being made
}
@HostListener('blur', ['$event'])
onBlur(event: KeyboardEvent) {
let value = this.element.value.replace(/[^\d\.]+/g, '');
value = this.decimalPipe.transform(value, '1.2-2');
this.element.value = value; // format for user, but don't change model
}
@HostListener('focus', ['$event'])
onFocus(event: KeyboardEvent) {
const input = event.target as HTMLInputElement;
input.value = this.trim(input.value); // format for user, but don't change model
}
}
Right now the only way I can think of doing something like this is loop through all the inputs in the page to force focus, get them to format, then set the form to be untouched again, which is a horrific solution.
I ended up using valueChanges on NgControl and then unsubscribing after the forms initial response was received. It didn't click until in VSCode showed valueChanges was an Observable.
public ngOnInit() {
const handle = this.ngControl.valueChanges
.subscribe((value: string) => {
this.element.value = this.decimalPipe.transform(value, '1.2-2');
handle.unsubscribe();
});
}