在Angular 6中使用区域设置将输入格式设置为数字 [英] Format input as number with locale in Angular 6
问题描述
我正在尝试在用户区域设置的文本输入中格式化数字.我尝试使用DecimalPipe
和自定义的自制管道,并且两者都在开始时起作用.问题是,一旦将数字格式化为字符串,管道便不再起作用,因为它应该应用于数字.
I am trying to format a number in a text input in the locale of the user. I tried to use DecimalPipe
and a custom self-made pipe and both work at first. The problem is, as soon as the number is formated into a string, the pipe doesn't work anymore since it is supposed to be applied on a number.
例如,当我键入1234.23
时,它显示1 234,23
,但是DecimalPipe在1 234,23
上不起作用,并且出现NaN错误.
So for example when I type 1234.23
, it displays 1 234,23
but the DecimalPipe doesn't work on 1 234,23
and I get the NaN error.
我没有发现任何可以将格式化后的文本重新转换为数字以重新应用管道的内容.例如Number("1 234,23")
不起作用并返回NaN ...
I didn't find anything that allows me to turn back the formatted text into a number again to reapply my pipe. For instance Number("1 234,23")
doesn't work and returns NaN...
很容易摆脱千位分隔符,但是有时它是一个逗号,有时逗号是十进制分隔符,因此我需要语言环境来定义如何将字符串格式化为数字.
It is easy to get rid of the thousand separator space, but sometimes it is a comma and sometimes the comma is the decimal separator, so I need the locale to define how the string is formatted into a number.
推荐答案
我为此创建了自定义输入组件,它在许多系统中都可以正常工作而没有任何问题.
I have created custom input component for this purpose and it is working fine in many system without any issue.
我在系统中使用ngx-translate处理国际化.这是我的实现.
I have used ngx-translate for handling Internationalization in my system. Here is my implementation.
HTML
<input #input type="text" appOnlyNumbers (input)="onChange($event)" (keyup.enter)="enterKeyEvent($event.target.value)" class="form-control text-right w-100"
[disabled]="disabled" (blur)="onBlur($event.target.value)" [(ngModel)]="value" />
Ts
import { Component, OnInit, ViewChild, ElementRef, Input, forwardRef, Output, EventEmitter } from '@angular/core';
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
import { TranslateService } from '@ngx-translate/core';
export const AMOUNT_VALUE_ACCESSOR: any = {
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => AmountInputComponent),
multi: true
};
@Component({
selector: 'app-amount-input',
templateUrl: './amount-input.component.html',
styleUrls: ['./amount-input.component.scss'],
providers: [AMOUNT_VALUE_ACCESSOR]
})
export class AmountInputComponent implements OnInit, ControlValueAccessor {
@ViewChild('input')
input: ElementRef;
locale: string;
value: any;
@Input() disabled = false;
@Input() hideClose = true;
@Output() valueChange = new EventEmitter<string>();
@Output() valueBlur = new EventEmitter<string>();
@Output() enterKey = new EventEmitter<string>();
changeCallback = (data: any) => { };
touchCallback = () => { };
constructor(
private translateService: TranslateService
) {
// these should be 'en-US', 'nd-NO','de-DE' etc, should setup on ngx-translate settings
this.locale = this.translateService.currentLang;
}
ngOnInit() {
// **Language selecton and subscription - amountconverter uses this **
this.translateService.onLangChange.subscribe(res => {
this.locale = res.lang;
this.input.nativeElement.value = this.format(this.value);
});
}
onChange(event) {
this.value = event.target.value;
this.changeCallback(event.target.value);
this.valueChange.emit(event.target.value);
}
writeValue(amount: any) {
this.value = amount;
this.input.nativeElement.value = this.format(amount);
this.changeCallback(this.input.nativeElement.value);
this.valueChange.emit(this.input.nativeElement.value);
this.value = this.input.nativeElement.value;
}
registerOnChange(fn: any) {
this.changeCallback = fn;
}
registerOnTouched(fn: any) {
this.touchCallback = fn;
}
setDisabledState(disabled: boolean) {
this.disabled = disabled;
}
format(value: number | string) {
let amount = value ? value.toString() : '0';
amount = amount.replace(/\s/g, '');
amount = amount.replace(/,/g, '');
amount = amount.replace(/\./g, '');
return (Number(amount) / 100).toLocaleString(this.locale, { minimumFractionDigits: 2 });
}
onBlur(value) {
this.writeValue(value);
this.valueBlur.emit(value);
}
enterKeyEvent(value) {
this.enterKey.emit(value);
this.input.nativeElement.value = this.format(value);
}
}
要了解有关数字转换的信息,请参见以下链接
To learn about number conversion refer following link
https://developer.mozilla.org /en-US/docs/Web/JavaScript/Reference/Global_Objects/NumberFormat
以下指令不允许在输入中添加不需要的字符.用于自定义组件的输入元素
Following directive will not allow to add unwanted characters to the input. Used in input element of custom component
import { Directive, HostListener, ElementRef } from '@angular/core';
@Directive({
selector: '[appOnlyNumbers]'
})
export class OnlyNumbersDirective {
constructor(private el: ElementRef) { }
@HostListener('keydown', ['$event']) onKeyDown(event) {
const e = <KeyboardEvent>event;
if ([46, 8, 9, 27, 13, 110, 188, 190].indexOf(e.keyCode) !== -1 ||
// Allow: Ctrl+A
(e.keyCode === 65 && e.ctrlKey === true) ||
// Allow: Ctrl+C
(e.keyCode === 67 && e.ctrlKey === true) ||
// Allow: Ctrl+X
(e.keyCode === 88 && e.ctrlKey === true) ||
// Allow: home, end, left, right
(e.keyCode >= 35 && e.keyCode <= 39)) {
// let it happen, don't do anything
return;
}
// Ensure that it is a number and stop the keypress
if ((e.shiftKey || (e.keyCode < 48 || e.keyCode > 57)) && (e.keyCode < 96 || e.keyCode > 105)) {
e.preventDefault();
}
}
}
用法:
<app-us-amount-input [(ngModel)]="Amount" (valueChange)="itemAmountChange()"></app-us-amount-input>
这也可以在内部反应形式中使用.
This can use inside reactive forms too.
<app-us-amount-input formControlName="Amount" (valueChange)="itemAmountChange()"></app-us-amount-input>
有时以下功能需要从组件获取输入值.
Sometimes following function will need to get value of input from component.
format(value: number | string) {
let amount = value ? value.toString() : '0';
amount = amount.replace(/\s/g, '');
amount = amount.replace(/,/g, '');
amount = amount.replace(/\./g, '');
return (Number(amount) / 100);
}
希望这对某人有帮助.
Hope this will help to someone.
这篇关于在Angular 6中使用区域设置将输入格式设置为数字的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!