Issue
i've only been learning Angular for a short time and I'm facing a problem. I have built a form using reactive forms. The user can enter an amount of money in an input field. When he leave the field, I would like the value to be automatically formatted into German notation. (e.g. 87.998,00) I don't need the euro symbol.
So far I haven't been able to find a solution to solve this with reactive forms via a pipe. Is it worth continuing to search or do I have to solve this using a classic Javascript function?
So far I've only managed to include the two decimal places.
validateCurrency(event: any){
let t = event.target.value;
event.target.value =
t.indexOf(',')>= 0
? t.substr(0, t.indexOf(',')) + t.substr(t.indexOf(','), 2)
: t;
}
Edit:
For an Example, here is my Form:
<form [formGroup]="decimalForm">
<input type="text" #userNumber (blur)="changeNumber()" formControlName="userNumber">
And the .ts of the component
import { Component, ElementRef, ViewChild } from '@angular/core';
import { FormControl, FormGroup } from '@angular/forms';
@Component({
selector: 'app-forms',
templateUrl: './forms.component.html',
styleUrl: './forms.component.scss'
})
export class FormsComponent {
public decimalForm: FormGroup = new FormGroup({
userNumber: new FormControl('Test')
})
@ViewChild("userNumber") userNumber!: ElementRef;
changeNumber() {
}
}
In the function changeNumer() I need the code, to change the value after the user leave the input.
Solution
Typical if you want to "formatting a number" in (blur) you use a directive
@Directive({
selector:'[formatNumber]',
standalone:true,
})
export class FormatNumberDirective implements AfterViewInit{
mask:string='.2-2'
@Input('formatNumber') set _(value:string)
{
this.mask=value||'.2-2'
}
//this is to align to right
@HostBinding('style.text-align') style='right'
//listen when (blur)
@HostListener('blur')
onBlur() {
this.parse()
}
//listen when focus
@HostListener('focus',['$event.target'])
onFocus(target:any) {
target.value=this.control?.control?.value|| ""
}
//the "el.nativeElement" is the "input"
//the control.control is the "control" (or NgModel or FormControl)
//we inject the "LOCALE_ID". This can be "hardcode" in provider or
//get the value when use Angular localize
constructor(@Inject(LOCALE_ID) private locale:string,
private el:ElementRef,
private control:NgControl){}
//at very first stage we can also that the value is showed "formatted"
ngAfterViewInit(){
setTimeout(()=>{
this.parse()
})
}
parse()
{
this.el.nativeElement.value=this.control?.control?.value?
formatNumber(this.control?.control?.value,this.locale,this.mask):
''
}
}
And use like
<input formatNumber [(ngModel)]="value"/>
<input formatNumber='1.2-2' [formControl]="control"/>
NOTE: Don't forget register your locale using registerLocaleData
Update
parse()
{
const value=''+(this.control?.control?.value||'')
this.el.nativeElement.value=value?
formatNumber(+(value.replace(',','.')),this.locale,this.mask):''
}
Generally, if we want to store in a dbs, the numbers should be in "standard format" (in en-US). But, we want to use the decimal separator in our locale.
So, we can declare a variable
decimalSymbol:string="."
and in constructor of the directive get the value
this.decimalSymbol=getLocaleNumberSymbol(this.locale, NumberSymbol.Decimal)
Now we need change a bit the functions parse and onFocus
@HostListener('focus',['$event.target'])
onFocus(target:any) {
target.value=this.decimalSymbol!='.'?
(this.control?.control?.value|| "").replace('.',this.decimalSymbol):
(this.control?.control?.value|| "")
}
parse()
{
const value=this.decimalSymbol!='.'?
+(''+(this.control?.control?.value||''))
.replace(this.decimalSymbol,'.'):
this.control?.control?.value
this.control.control?.setValue(value, { emit: false });
this.el.nativeElement.value=value?formatNumber(value,this.locale,this.mask):''
}
Just corrected in stackblitz
Answered By - Eliseo
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.