Angular 2:ngModel 输入上的 "number" 管道出现游标问题
Angular 2: Cursor issue with "number" pipe on ngModel input
我有一个输入要像货币一样显示。我只希望允许两位小数,并且只允许数字,同时在必要时自动添加逗号。基本上,如果用户键入“12345”,我希望输入自动显示为“12,345.00”。 “12,345”也可以接受,但如果他们输入“12345.5”,则需要显示为“12,345.50”。我正在尝试使用管道来完成此操作并决定使用 "number" 管道,因为我不想显示货币符号(我在输入之前已经有一个美元符号作为标签)。
这是我的代码:
<input [ngModel]="Amount | number: '1.2-2'" (ngModelChange)="updateAmount($event)" class="form-control" id="Amount" name="Amount" tabindex="4" type="number" autocomplete="off">
我遇到了一些问题。
- 当我输入一个数字时,它会自动在末尾添加一个小数和两个 0,这很好,但它还会将光标添加到数字的最后,所以如果我输入“55”,而不是显示为“55.00”,它显示为“5.01”(我假设它将其解释为 5.005,然后将其四舍五入为 5.01)。我怎样才能防止光标移动到最后,以便用户可以在看到他们期望的结果的同时自然地键入?
- 此过滤器实际上并未将输入限制为小数点后两位。如果我输入“1234”,它将显示为“1.00234”。它还将允许我添加多个小数点。我怎样才能将它限制为一位小数点后只有两位数?
- 输错这个管道真的很容易断。例如,如果用户输入一个字母,我将在控制台中收到类似以下内容的错误:
Invalid argument '11.00a' for pipe 'DecimalPipe'
此错误后,过滤器完全停止工作。
如果我将输入设置为 type="number"
并输入 1234,该值将为 1,234,但输入将消失并且我将在我的控制台中收到以下消息:
The specified value "1,234" is not a valid number. The value must match to the following regular expression: -?(\d+|\d+.\d+|.\d+)([eE][-+]?\d+)?
使用 JQuery Inputmask 给出了我想要的 restricting/displaying 输入结果,但它破坏了我的 ngModel 并将值设置为空,所以这不是我的选择除非有人知道解决办法。
是否可以对我的管道进行更改以获得我想要的结果?我怎样才能让它工作?
这是前面提到的屏蔽输入的指令:
https://plnkr.co/edit/aBvO2F?p=preview
import { Directive } from "@angular/core";
import { NgControl } from "@angular/forms";
@Directive({
selector: '[ngModel][decimal]',
host: {
'(ngModelChange)': 'onInputChange($event)'
}
})
export class DecimalMask {
constructor(public model: NgControl) {}
onInputChange(event, backspace) {
var valArray = event.toString().split('.') : [];
for(var i = 0; i < valArray.length; ++i) {
valArray[i] = valArray[i].replace(/\D/g, '');
}
var newVal: number;
if(valArray.length === 0) {
newVal = '';
}
else {
let matches = valArray[0].match(/[0-9]{3}/mig);
if(matches !== null && valArray[0].length > 3) {
let commaGroups = Array.from(Array.from(valArray[0]).reverse().join('').match(/[0-9]{3}/mig).join()).reverse().join('');
let replacement = valArray[0].replace(commaGroups.replace(/\D/g, ''), '');
newVal = (replacement.length > 0 ? replacement + "," : "") + commaGroups;
} else {
newVal = valArray[0];
}
if(valArray.length > 1) {
newVal += "." + valArray[1].substring(0,2);
}
}
// set the new value
this.model.valueAccessor.writeValue(newVal);
}
}
输入元素看起来像:
<input decimal [(ngModel)]="Amount"
class="form-control" id="Amount" name="Amount" tabindex="4" autocomplete="off">
如果最后一个字符是字母或小数点后的长度 > 2,请检查防护:
ngDoCheck() {
console.log(this.Amount);
if(this.Amount) {
this.Amount = this.Amount.replace(/[A-Za-z]/g, '');
if(this.Amount.indexOf('.') !== -1) {
var arrayVals = this.Amount.split('.');
this.Amount = arrayVals[0] + "." + arrayVals[1].slice(0,2);
}
}
}
我有一个输入要像货币一样显示。我只希望允许两位小数,并且只允许数字,同时在必要时自动添加逗号。基本上,如果用户键入“12345”,我希望输入自动显示为“12,345.00”。 “12,345”也可以接受,但如果他们输入“12345.5”,则需要显示为“12,345.50”。我正在尝试使用管道来完成此操作并决定使用 "number" 管道,因为我不想显示货币符号(我在输入之前已经有一个美元符号作为标签)。
这是我的代码:
<input [ngModel]="Amount | number: '1.2-2'" (ngModelChange)="updateAmount($event)" class="form-control" id="Amount" name="Amount" tabindex="4" type="number" autocomplete="off">
我遇到了一些问题。
- 当我输入一个数字时,它会自动在末尾添加一个小数和两个 0,这很好,但它还会将光标添加到数字的最后,所以如果我输入“55”,而不是显示为“55.00”,它显示为“5.01”(我假设它将其解释为 5.005,然后将其四舍五入为 5.01)。我怎样才能防止光标移动到最后,以便用户可以在看到他们期望的结果的同时自然地键入?
- 此过滤器实际上并未将输入限制为小数点后两位。如果我输入“1234”,它将显示为“1.00234”。它还将允许我添加多个小数点。我怎样才能将它限制为一位小数点后只有两位数?
- 输错这个管道真的很容易断。例如,如果用户输入一个字母,我将在控制台中收到类似以下内容的错误:
Invalid argument '11.00a' for pipe 'DecimalPipe'
此错误后,过滤器完全停止工作。
如果我将输入设置为 type="number"
并输入 1234,该值将为 1,234,但输入将消失并且我将在我的控制台中收到以下消息:
The specified value "1,234" is not a valid number. The value must match to the following regular expression: -?(\d+|\d+.\d+|.\d+)([eE][-+]?\d+)?
使用 JQuery Inputmask 给出了我想要的 restricting/displaying 输入结果,但它破坏了我的 ngModel 并将值设置为空,所以这不是我的选择除非有人知道解决办法。
是否可以对我的管道进行更改以获得我想要的结果?我怎样才能让它工作?
这是前面提到的屏蔽输入的指令: https://plnkr.co/edit/aBvO2F?p=preview
import { Directive } from "@angular/core";
import { NgControl } from "@angular/forms";
@Directive({
selector: '[ngModel][decimal]',
host: {
'(ngModelChange)': 'onInputChange($event)'
}
})
export class DecimalMask {
constructor(public model: NgControl) {}
onInputChange(event, backspace) {
var valArray = event.toString().split('.') : [];
for(var i = 0; i < valArray.length; ++i) {
valArray[i] = valArray[i].replace(/\D/g, '');
}
var newVal: number;
if(valArray.length === 0) {
newVal = '';
}
else {
let matches = valArray[0].match(/[0-9]{3}/mig);
if(matches !== null && valArray[0].length > 3) {
let commaGroups = Array.from(Array.from(valArray[0]).reverse().join('').match(/[0-9]{3}/mig).join()).reverse().join('');
let replacement = valArray[0].replace(commaGroups.replace(/\D/g, ''), '');
newVal = (replacement.length > 0 ? replacement + "," : "") + commaGroups;
} else {
newVal = valArray[0];
}
if(valArray.length > 1) {
newVal += "." + valArray[1].substring(0,2);
}
}
// set the new value
this.model.valueAccessor.writeValue(newVal);
}
}
输入元素看起来像:
<input decimal [(ngModel)]="Amount"
class="form-control" id="Amount" name="Amount" tabindex="4" autocomplete="off">
如果最后一个字符是字母或小数点后的长度 > 2,请检查防护:
ngDoCheck() {
console.log(this.Amount);
if(this.Amount) {
this.Amount = this.Amount.replace(/[A-Za-z]/g, '');
if(this.Amount.indexOf('.') !== -1) {
var arrayVals = this.Amount.split('.');
this.Amount = arrayVals[0] + "." + arrayVals[1].slice(0,2);
}
}
}