在angular8中收到错误消息后如何将金额转换为货币管道值
How to get the amount converted to currency pipe value after getting error message in angular8
我在模糊事件中使用货币管道。但它第一次工作正常,当我收到验证错误消息时,如果我删除几个数字并出来,它不会被格式化为货币格式,仍保留用户删除的格式。
例如我给了这个号码:
36543265
所以当我从输入中出来时,它被格式化为 ,543,265.00
,并带有验证错误消息。所以如果我删除
265.00
来自 ,543,265.00
,我仍然收到错误验证消息。所以验证错误消息消失并保持这种格式 ,543
但它没有达到正确的格式。清除验证消息后,如何使其成为 USD
的正确货币管道格式。
如何根据用户删除的值使其正确格式化。
TS:
public transformAmount(element, name) {
if (name == "amount") {
let formattedAmount = this.currencyPipe.transform(this.eoInfoForm.value.amount, 'USD');
element.target.value = formattedAmount;
this.eoInfoForm.get('amount').setValue(formattedAmount);
if (this.eoInfoForm.get('amount').status === 'VALID') {
this.amt = false;
}
else {
this.amt = true;
}
}
}
HTML:
<input type="text" class="form-control" placeholder="Amount in dolars"
formControlName="amount" autocomplete="off" maxlength="8" allowNumberOnly (blur)="transformAmount($event,'amount')" [ngClass]="{ 'is-invalid': amt && eoInfo.amount.invalid }">
<div *ngIf="amt && eoInfo.amount.invalid" class="invalid-feedback">
<div *ngIf="amt && eoInfo.amount.invalid">Maximum of 8 characters including $ is allowed</div>
</div>
演示:
DEMO
插入 $ 符号后,您的代码出现错误
您可以使用此正则表达式仅从文本中获取数字
var thenum = thestring.replace( /^\D+/g, ''); // replace all leading non-digits with nothing
或者只检查第一个字符,如果是 $ 则将其删除
为了使其正常工作,我更改了您的代码中的一些内容:Working solution
这是主要部分:
public transformAmount(name) {
let formattedAmount = this.currencyPipe.transform(
this.eoInfoForm.value.amount.replace(/[^\d.E+]/gm, ""),
"USD"
);
this.eoInfoForm.get(name).setValue(formattedAmount);
}
我所做的是在将值再次传递给管道之前反转管道转换。我使用 /[^\d.E+]/gm
正则表达式删除了未包含在 :
中的所有内容
- 人数
- 点字符
- "E" 字符
- “+”字符
"E"和“+”是为了处理数字非常大,显示为.00E+37
的特定情况。
我认为最大长度为 8 是在文本已格式化时适用的,所以我没有碰它(否则你需要一个自定义验证器)。我只是将其移至 TypeScript 文件,因为您使用的是响应式表单,所以最好不要混合模板表单概念。
您可以编写一个稍微简单的指令来执行此操作:
import { Directive, HostListener, ElementRef, OnInit, Input } from "@angular/core";
import { CurrencyPipe } from '@angular/common';
@Directive({ selector: "[currencyInput]" })
export class CurrencyInputDirective implements OnInit {
// build the regex based on max pre decimal digits allowed
private regexString(max?: number) {
const maxStr = max ? `{0,${max}}` : `+`;
return `^(\d${maxStr}(\.\d{0,2})?|\.\d{0,2})$`
}
private digitRegex: RegExp;
private setRegex(maxDigits?: number) {
this.digitRegex = new RegExp(this.regexString(maxDigits), 'g')
}
@Input()
set maxDigits(maxDigits: number) {
this.setRegex(maxDigits);
}
private el: HTMLInputElement;
constructor(
private elementRef: ElementRef,
private currencyPipe: CurrencyPipe
) {
this.el = this.elementRef.nativeElement;
this.setRegex();
}
ngOnInit() {
this.el.value = this.currencyPipe.transform(this.el.value, 'USD');
}
@HostListener("focus", ["$event.target.value"])
onFocus(value) {
// on focus remove currency formatting
this.el.value = value.replace(/[^0-9.]+/g, '')
}
@HostListener("blur", ["$event.target.value"])
onBlur(value) {
// on blur, add currency formatting
this.el.value = this.currencyPipe.transform(value, 'USD');
}
// variable to store last valid input
private lastValid = '';
@HostListener('input', ['$event'])
onInput(event) {
// on input, run regex to only allow certain characters and format
const cleanValue = (event.target.value.match(this.digitRegex) || []).join('')
if (cleanValue || !event.target.value)
this.lastValid = cleanValue
this.el.value = cleanValue || this.lastValid
}
}
该指令将值转换为焦点上的数字,并在模糊时返回格式化的货币字符串。
像这样使用:
<input type="text" class="form-control" placeholder="Amount in dolars" autocomplete="off"
formControlName="amount" currencyInput maxDigits="9"
[ngClass]="{ 'is-invalid': eoInfo.amount.dirty && eoInfo.amount.invalid }">
闪电战:https://stackblitz.com/edit/angular-csyslb?file=src%2Fapp%2Fcurrency-input.directive.ts
首先我要指出的是:
您使用 maxlength="8"
这很好,直到您开始使用货币管道。您的货币管道添加的字符将被考虑在内。我不知道这是否是一种想要的行为,但从用户的角度来看,这绝对是不直观的。
"I see a limit of 8 characters, I can input up to 8 characters" -
是我在阅读验证消息时首先想到的。我不想在输入(当时)未格式化的数字时自己考虑货币格式。
我会说要么使 maxLength
14(8 + 1 美元符号 + 2 个逗号 + 1 个点 + 两位数是 USD = 14 个字符的最大可能数)并将验证消息保留为值为 8。或者,如果您在格式化后真的只想要 8 个字符,请将验证消息值设置为 3(3 + 1 美元符号 + 1 个逗号 + 1 个点 + 双位数 = 7),格式化后有 4 个数字变为 9 个字符,因为添加了额外的数字+逗号,将达到 9 个字符,这比 maxLength 8 多。
您还可以对长度使用自定义验证并正确检查自己(如果货币格式可以变化,这很好)而不是依赖通用 *ngIf="amt && eoInfo.amount.invalid"
现在对于您的实际问题,我认为一个很好的解决方案是在编辑时删除格式。对于用户来说,编辑并不得不在 .
,
和 $
之间导航是不切实际的,因为他们在编辑时真正关心的是数字。
当用户聚焦该字段时,您可以制作一个 "reverse currency pipe",这样他们看到的就是数字。
我假设最大长度是指小数点前的位数,我对你的 Stackblitz demo 进行了快速分叉。
让我知道是否有任何需要更改的地方,以及这是否有助于解决您的问题。
我在模糊事件中使用货币管道。但它第一次工作正常,当我收到验证错误消息时,如果我删除几个数字并出来,它不会被格式化为货币格式,仍保留用户删除的格式。
例如我给了这个号码:
36543265
所以当我从输入中出来时,它被格式化为 ,543,265.00
,并带有验证错误消息。所以如果我删除
265.00
来自 ,543,265.00
,我仍然收到错误验证消息。所以验证错误消息消失并保持这种格式 ,543
但它没有达到正确的格式。清除验证消息后,如何使其成为 USD
的正确货币管道格式。
如何根据用户删除的值使其正确格式化。
TS:
public transformAmount(element, name) {
if (name == "amount") {
let formattedAmount = this.currencyPipe.transform(this.eoInfoForm.value.amount, 'USD');
element.target.value = formattedAmount;
this.eoInfoForm.get('amount').setValue(formattedAmount);
if (this.eoInfoForm.get('amount').status === 'VALID') {
this.amt = false;
}
else {
this.amt = true;
}
}
}
HTML:
<input type="text" class="form-control" placeholder="Amount in dolars"
formControlName="amount" autocomplete="off" maxlength="8" allowNumberOnly (blur)="transformAmount($event,'amount')" [ngClass]="{ 'is-invalid': amt && eoInfo.amount.invalid }">
<div *ngIf="amt && eoInfo.amount.invalid" class="invalid-feedback">
<div *ngIf="amt && eoInfo.amount.invalid">Maximum of 8 characters including $ is allowed</div>
</div>
演示: DEMO
插入 $ 符号后,您的代码出现错误
您可以使用此正则表达式仅从文本中获取数字
var thenum = thestring.replace( /^\D+/g, ''); // replace all leading non-digits with nothing
或者只检查第一个字符,如果是 $ 则将其删除
为了使其正常工作,我更改了您的代码中的一些内容:Working solution
这是主要部分:
public transformAmount(name) {
let formattedAmount = this.currencyPipe.transform(
this.eoInfoForm.value.amount.replace(/[^\d.E+]/gm, ""),
"USD"
);
this.eoInfoForm.get(name).setValue(formattedAmount);
}
我所做的是在将值再次传递给管道之前反转管道转换。我使用 /[^\d.E+]/gm
正则表达式删除了未包含在 :
- 人数
- 点字符
- "E" 字符
- “+”字符
"E"和“+”是为了处理数字非常大,显示为.00E+37
的特定情况。
我认为最大长度为 8 是在文本已格式化时适用的,所以我没有碰它(否则你需要一个自定义验证器)。我只是将其移至 TypeScript 文件,因为您使用的是响应式表单,所以最好不要混合模板表单概念。
您可以编写一个稍微简单的指令来执行此操作:
import { Directive, HostListener, ElementRef, OnInit, Input } from "@angular/core";
import { CurrencyPipe } from '@angular/common';
@Directive({ selector: "[currencyInput]" })
export class CurrencyInputDirective implements OnInit {
// build the regex based on max pre decimal digits allowed
private regexString(max?: number) {
const maxStr = max ? `{0,${max}}` : `+`;
return `^(\d${maxStr}(\.\d{0,2})?|\.\d{0,2})$`
}
private digitRegex: RegExp;
private setRegex(maxDigits?: number) {
this.digitRegex = new RegExp(this.regexString(maxDigits), 'g')
}
@Input()
set maxDigits(maxDigits: number) {
this.setRegex(maxDigits);
}
private el: HTMLInputElement;
constructor(
private elementRef: ElementRef,
private currencyPipe: CurrencyPipe
) {
this.el = this.elementRef.nativeElement;
this.setRegex();
}
ngOnInit() {
this.el.value = this.currencyPipe.transform(this.el.value, 'USD');
}
@HostListener("focus", ["$event.target.value"])
onFocus(value) {
// on focus remove currency formatting
this.el.value = value.replace(/[^0-9.]+/g, '')
}
@HostListener("blur", ["$event.target.value"])
onBlur(value) {
// on blur, add currency formatting
this.el.value = this.currencyPipe.transform(value, 'USD');
}
// variable to store last valid input
private lastValid = '';
@HostListener('input', ['$event'])
onInput(event) {
// on input, run regex to only allow certain characters and format
const cleanValue = (event.target.value.match(this.digitRegex) || []).join('')
if (cleanValue || !event.target.value)
this.lastValid = cleanValue
this.el.value = cleanValue || this.lastValid
}
}
该指令将值转换为焦点上的数字,并在模糊时返回格式化的货币字符串。
像这样使用:
<input type="text" class="form-control" placeholder="Amount in dolars" autocomplete="off"
formControlName="amount" currencyInput maxDigits="9"
[ngClass]="{ 'is-invalid': eoInfo.amount.dirty && eoInfo.amount.invalid }">
闪电战:https://stackblitz.com/edit/angular-csyslb?file=src%2Fapp%2Fcurrency-input.directive.ts
首先我要指出的是:
您使用 maxlength="8"
这很好,直到您开始使用货币管道。您的货币管道添加的字符将被考虑在内。我不知道这是否是一种想要的行为,但从用户的角度来看,这绝对是不直观的。
"I see a limit of 8 characters, I can input up to 8 characters" - 是我在阅读验证消息时首先想到的。我不想在输入(当时)未格式化的数字时自己考虑货币格式。
我会说要么使 maxLength
14(8 + 1 美元符号 + 2 个逗号 + 1 个点 + 两位数是 USD = 14 个字符的最大可能数)并将验证消息保留为值为 8。或者,如果您在格式化后真的只想要 8 个字符,请将验证消息值设置为 3(3 + 1 美元符号 + 1 个逗号 + 1 个点 + 双位数 = 7),格式化后有 4 个数字变为 9 个字符,因为添加了额外的数字+逗号,将达到 9 个字符,这比 maxLength 8 多。
您还可以对长度使用自定义验证并正确检查自己(如果货币格式可以变化,这很好)而不是依赖通用 *ngIf="amt && eoInfo.amount.invalid"
现在对于您的实际问题,我认为一个很好的解决方案是在编辑时删除格式。对于用户来说,编辑并不得不在 .
,
和 $
之间导航是不切实际的,因为他们在编辑时真正关心的是数字。
当用户聚焦该字段时,您可以制作一个 "reverse currency pipe",这样他们看到的就是数字。
我假设最大长度是指小数点前的位数,我对你的 Stackblitz demo 进行了快速分叉。
让我知道是否有任何需要更改的地方,以及这是否有助于解决您的问题。