I created a directive to format money in a text input. The blur and focus events work but if there is already a value in ngModel, it does not format the number. Once you give focus and leave the input, it formats properly. While debugging, you can see the template update with the formatted value during ngOnInit, but when you click continue, the value is no longer formatted.
money-input.directive.ts
import { CurrencyPipe } from '@angular/common';
import {
Directive,
EventEmitter,
HostListener,
Injector,
Input,
Output,
} from '@angular/core';
import { NgControl, NgModel } from '@angular/forms';
@Directive({
selector: '[moneyInput]',
providers: [NgModel],
host: {
'(input)': 'onInputChange($event)',
},
})
export class MoneyInputDirective {
@Input() ngModel;
@Output() ngModelChange: EventEmitter<any> = new EventEmitter();
value: number;
private control: NgControl;
constructor(private currencyPipe: CurrencyPipe, private injector: Injector) {}
ngOnInit() {
this.control = this.injector.get(NgControl);
if (!this.control || !this.control.valueAccessor) {
return;
}
this.value = Number(this.ngModel);
this.formatCurrency();
}
@HostListener('blur') onBlur() {
this.formatCurrency();
}
@HostListener('focus') onFocus() {
this.control.valueAccessor.writeValue(this.value);
}
onInputChange($event) {
if (!isNaN(Number($event.target.value))) {
this.value = Number($event.target.value);
}
this.ngModelChange.emit(this.value);
}
formatCurrency() {
if (!isNaN(Number(this.ngModel))) {
this.control.valueAccessor.writeValue(
this.currencyPipe.transform(this.ngModel)
);
} else {
this.control.valueAccessor.writeValue('');
}
}
}
app.component.html
<input type="text" [(ngModel)]="model" moneyInput />
Link to StackBlitz project https://stackblitz.com/edit/angular-money-input-directive?file=src/app/app.component.html
CodePudding user response:
Move the format behind a timeout:
setTimeout(() => {
this.control.valueAccessor.writeValue(
this.currencyPipe.transform(this.ngModel)
);
})
So that it hits another digest cycle, that seems to make it work.
