别忘了处理退格键、光标位置和美国运通
我必须处理一些额外的复杂性,但这可能是许多人在开发时会遇到的问题。在重写输入值时,我们需要考虑使用Backspace 键和箭头键。还需要考虑美国运通号码,而不仅仅是 4-4-4-4 号码。
这是我在组件中使用模板引用变量和光标位置检测的方法。 (如果您只有一个获取信用卡号码的组件,则不需要自定义指令,这通常是这种情况。)
要处理Backspace 和光标箭头键,我们必须存储原始光标位置并在从字符串末尾以外的任何位置编辑后恢复它。
为了能够处理美国运通,我使用一个名为partitions 的变量来存储美国运通卡的 4-6-5 间距格式和所有其他卡的 4-4-4-4 间距格式。我们在添加空格时循环partitions。
/* Insert spaces to make CC number more legible */
cardNumberSpacing() {
const input = this.ccNumberField.nativeElement;
const { selectionStart } = input;
const { cardNumber } = this.paymentForm.controls;
let trimmedCardNum = cardNumber.value.replace(/\s+/g, '');
if (trimmedCardNum.length > 16) {
trimmedCardNum = trimmedCardNum.substr(0, 16);
}
/* Handle American Express 4-6-5 spacing format */
const partitions = trimmedCardNum.startsWith('34') || trimmedCardNum.startsWith('37')
? [4,6,5]
: [4,4,4,4];
const numbers = [];
let position = 0;
partitions.forEach(partition => {
const part = trimmedCardNum.substr(position, partition);
if (part) numbers.push(part);
position += partition;
})
cardNumber.setValue(numbers.join(' '));
/* Handle caret position if user edits the number later */
if (selectionStart < cardNumber.value.length - 1) {
input.setSelectionRange(selectionStart, selectionStart, 'none');
}
}
如果您有自己的例程来检测美国运通号码,请使用它。我在这里使用的只是检查前两位数字并将它们与PAN/IIN standards 进行比较。
在你的组件中,确保你有正确的导入:
import { ViewChild, ElementRef } from '@angular/core';
还有:
@ViewChild('ccNumber') ccNumberField: ElementRef;
当您设置表单控件时,请执行以下操作,以便在您的正则表达式模式中包含空格:
this.paymentForm = this.fb.group({
cardNumber: ['', [Validators.required, Validators.pattern('^[ 0-9]*$';), Validators.minLength(17)]]
})
最后,在您的模板中,像这样配置您的元素:
<input maxlength="20"
formControlName="cardNumber"
type="tel"
#ccNumber
(keyup)="cardNumberSpacing()">
你应该很高兴!