Html Angular2 - 仅接受数字的输入字段
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/41465542/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Angular2 - Input Field To Accept Only Numbers
提问by Aniruddha Pondhe
In Angular 2, how can I mask an input field (textbox) such that it accepts only numbers and not alphabetical characters?
在 Angular 2 中,如何屏蔽输入字段(文本框),使其只接受数字而不接受字母字符?
I have the following HTML input:
我有以下 HTML 输入:
<input
type="text"
*ngSwitchDefault
class="form-control"
(change)="onInputChange()"
[(ngModel)]="config.Value"
(focus)="handleFocus($event)"
(blur)="handleBlur($event)"
/>
The above input is a generic text input which may either be used as a simple text field or as a numeric field, for example, to show the year.
上面的输入是一个通用的文本输入,它既可以用作简单的文本字段,也可以用作数字字段,例如,显示年份。
Using Angular 2, how can I use the same input control and apply some sort of filter/mask on this field, such that it accepts only numbers?
使用 Angular 2,如何使用相同的输入控件并在该字段上应用某种过滤器/掩码,使其仅接受数字?
What are the different ways I can achieve this?
我可以通过哪些不同的方式实现这一目标?
Note: I need to achieve this using only textbox and not using input number type.
注意:我只需要使用文本框而不是使用输入数字类型来实现这一点。
回答by omeralper
You can use angular2 directives. Plunkr
您可以使用 angular2 指令。普朗克
import { Directive, ElementRef, HostListener, Input } from '@angular/core';
@Directive({
selector: '[OnlyNumber]'
})
export class OnlyNumber {
constructor(private el: ElementRef) { }
@Input() OnlyNumber: boolean;
@HostListener('keydown', ['$event']) onKeyDown(event) {
let e = <KeyboardEvent> event;
if (this.OnlyNumber) {
if ([46, 8, 9, 27, 13, 110, 190].indexOf(e.keyCode) !== -1 ||
// Allow: Ctrl+A
(e.keyCode === 65 && (e.ctrlKey || e.metaKey)) ||
// Allow: Ctrl+C
(e.keyCode === 67 && (e.ctrlKey || e.metaKey)) ||
// Allow: Ctrl+V
(e.keyCode === 86 && (e.ctrlKey || e.metaKey)) ||
// Allow: Ctrl+X
(e.keyCode === 88 && (e.ctrlKey || e.metaKey)) ||
// 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();
}
}
}
}
and you need to write the directive name in your input as an attribute
并且您需要在输入中写入指令名称作为属性
<input OnlyNumber="true" />
don't forget to write your directive in declarations array of your module.
不要忘记在模块的声明数组中编写指令。
By using regex you would still need functional keys
通过使用正则表达式,您仍然需要功能键
export class OnlyNumber {
regexStr = '^[0-9]*$';
constructor(private el: ElementRef) { }
@Input() OnlyNumber: boolean;
@HostListener('keydown', ['$event']) onKeyDown(event) {
let e = <KeyboardEvent> event;
if (this.OnlyNumber) {
if ([46, 8, 9, 27, 13, 110, 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+V
(e.keyCode == 86 && 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;
}
let ch = String.fromCharCode(e.keyCode);
let regEx = new RegExp(this.regexStr);
if(regEx.test(ch))
return;
else
e.preventDefault();
}
}
}
回答by rashidnk
If you don't want a directive
如果你不想要一个指令
https://stackblitz.com/edit/numeric-only
https://stackblitz.com/edit/numeric-only
in component.html
在 component.html
<input (keypress)="numberOnly($event)" type="text">
in component.ts
在 component.ts
export class AppComponent {
numberOnly(event): boolean {
const charCode = (event.which) ? event.which : event.keyCode;
if (charCode > 31 && (charCode < 48 || charCode > 57)) {
return false;
}
return true;
}
}
回答by JeanPaul A.
I would like to build on the answer given by @omeralper , which in my opinion provided a good foundation for a solid solution.
我想以 @omeralper 给出的答案为基础,在我看来,它为可靠的解决方案提供了良好的基础。
What I am proposing is a simplified and up to date version with the latest web standards. It is important to note that event.keycode is removed from the web standards, and future browser updates might not support it anymore. See https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/keyCode
我提出的是一个简化的、最新的版本,符合最新的网络标准。重要的是要注意 event.keycode 已从 Web 标准中删除,未来的浏览器更新可能不再支持它。请参阅https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/keyCode
Furthermore, the method
此外,该方法
String.fromCharCode(e.keyCode);
does not guarantee that the keyCode pertaining to the key being pressed by the user maps to the expected letter as identified on the user's keyboard, since different keyboard configurations will result in a particular keycode different characters. Using this will introduce bugs which are difficult to identify, and can easily break the functionality for certain users. Rather I'm proposing the use of event.key, see docs here https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key
不保证与用户按下的键有关的 keyCode 映射到用户键盘上标识的预期字母,因为不同的键盘配置将导致特定的 keycode 不同的字符。使用它会引入难以识别的错误,并且很容易破坏某些用户的功能。相反,我建议使用 event.key,请参阅此处的文档https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key
Furthermore, we only want that the resultant output is a valid decimal. This means that the numbers 1, 11.2, 5000.2341234 should be accepted, but the value 1.1.2 should not be accepted.
此外,我们只希望结果输出是有效的小数。这意味着应接受数字 1、11.2、5000.2341234,但不应接受值 1.1.2。
Note that in my solution i'm excluding cut, copy and paste functionality since it open windows for bugs, especially when people paste unwanted text in associated fields. That would required a cleanup process on a keyup handler; which isn't the scope of this thread.
请注意,在我的解决方案中,我排除了剪切、复制和粘贴功能,因为它会为错误打开窗口,尤其是当人们在相关字段中粘贴不需要的文本时。这将需要对 keyup 处理程序进行清理过程;这不是这个线程的范围。
Here is the solution i'm proposing.
这是我提出的解决方案。
import { Directive, ElementRef, HostListener } from '@angular/core';
@Directive({
selector: '[myNumberOnly]'
})
export class NumberOnlyDirective {
// Allow decimal numbers. The \. is only allowed once to occur
private regex: RegExp = new RegExp(/^[0-9]+(\.[0-9]*){0,1}$/g);
// Allow key codes for special events. Reflect :
// Backspace, tab, end, home
private specialKeys: Array<string> = [ 'Backspace', 'Tab', 'End', 'Home' ];
constructor(private el: ElementRef) {
}
@HostListener('keydown', [ '$event' ])
onKeyDown(event: KeyboardEvent) {
// Allow Backspace, tab, end, and home keys
if (this.specialKeys.indexOf(event.key) !== -1) {
return;
}
// Do not use event.keycode this is deprecated.
// See: https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/keyCode
let current: string = this.el.nativeElement.value;
// We need this because the current value on the DOM element
// is not yet updated with the value from this event
let next: string = current.concat(event.key);
if (next && !String(next).match(this.regex)) {
event.preventDefault();
}
}
}
回答by Elvis Fernandez
I know this is an old question, but since this is a common funcionality, I want to share the modifications I've made:
我知道这是一个老问题,但由于这是一个常见的功能,我想分享我所做的修改:
- Custom decimal separator (point or comma)
- Support for integers only or integer and decimals
- Support for positive numbers only or positives and negatives
- Validate minus sign(-) is in the beginning
- Support to mouse pasting (with some limitation though https://caniuse.com/#feat=clipboard)
- Support for Mac command key
Replace strings like ".33" and "33." for the correct versions: 0.33 and 33.0
import { Directive, ElementRef, HostListener, Input } from '@angular/core'; @Directive({ selector: '[NumbersOnly]' }) export class NumbersOnly { @Input() allowDecimals: boolean = true; @Input() allowSign: boolean = false; @Input() decimalSeparator: string = '.'; previousValue: string = ''; // -------------------------------------- // Regular expressions integerUnsigned: string = '^[0-9]*$'; integerSigned: string = '^-?[0-9]+$'; decimalUnsigned: string = '^[0-9]+(.[0-9]+)?$'; decimalSigned: string = '^-?[0-9]+(.[0-9]+)?$'; /** * Class constructor * @param hostElement */ constructor(private hostElement: ElementRef) { } /** * Event handler for host's change event * @param e */ @HostListener('change', ['$event']) onChange(e) { this.validateValue(this.hostElement.nativeElement.value); } /** * Event handler for host's paste event * @param e */ @HostListener('paste', ['$event']) onPaste(e) { // get and validate data from clipboard let value = e.clipboardData.getData('text/plain'); this.validateValue(value); e.preventDefault(); } /** * Event handler for host's keydown event * @param event */ @HostListener('keydown', ['$event']) onKeyDown(e: KeyboardEvent) { let cursorPosition: number = e.target['selectionStart']; let originalValue: string = e.target['value']; let key: string = this.getName(e); let controlOrCommand = (e.ctrlKey === true || e.metaKey === true); let signExists = originalValue.includes('-'); let separatorExists = originalValue.includes(this.decimalSeparator); // allowed keys apart from numeric characters let allowedKeys = [ 'Backspace', 'ArrowLeft', 'ArrowRight', 'Escape', 'Tab' ]; // when decimals are allowed, add // decimal separator to allowed codes when // its position is not close to the the sign (-. and .-) let separatorIsCloseToSign = (signExists && cursorPosition <= 1); if (this.allowDecimals && !separatorIsCloseToSign && !separatorExists) { if (this.decimalSeparator == '.') allowedKeys.push('.'); else allowedKeys.push(','); } // when minus sign is allowed, add its // key to allowed key only when the // cursor is in the first position, and // first character is different from // decimal separator let firstCharacterIsSeparator = (originalValue.charAt(0) != this.decimalSeparator); if (this.allowSign && !signExists && firstCharacterIsSeparator && cursorPosition == 0) { allowedKeys.push('-'); } // allow some non-numeric characters if (allowedKeys.indexOf(key) != -1 || // Allow: Ctrl+A and Command+A (key == 'a' && controlOrCommand) || // Allow: Ctrl+C and Command+C (key == 'c' && controlOrCommand) || // Allow: Ctrl+V and Command+V (key == 'v' && controlOrCommand) || // Allow: Ctrl+X and Command+X (key == 'x' && controlOrCommand)) { // let it happen, don't do anything return; } // save value before keydown event this.previousValue = originalValue; // allow number characters only let isNumber = (new RegExp(this.integerUnsigned)).test(key); if (isNumber) return; else e.preventDefault(); } /** * Test whether value is a valid number or not * @param value */ validateValue(value: string): void { // choose the appropiate regular expression let regex: string; if (!this.allowDecimals && !this.allowSign) regex = this.integerUnsigned; if (!this.allowDecimals && this.allowSign) regex = this.integerSigned; if (this.allowDecimals && !this.allowSign) regex = this.decimalUnsigned; if (this.allowDecimals && this.allowSign) regex = this.decimalSigned; // when a numbers begins with a decimal separator, // fix it adding a zero in the beginning let firstCharacter = value.charAt(0); if (firstCharacter == this.decimalSeparator) value = 0 + value; // when a numbers ends with a decimal separator, // fix it adding a zero in the end let lastCharacter = value.charAt(value.length-1); if (lastCharacter == this.decimalSeparator) value = value + 0; // test number with regular expression, when // number is invalid, replace it with a zero let valid: boolean = (new RegExp(regex)).test(value); this.hostElement.nativeElement['value'] = valid ? value : 0; } /** * Get key's name * @param e */ getName(e): string { if (e.key) { return e.key; } else { // for old browsers if (e.keyCode && String.fromCharCode) { switch (e.keyCode) { case 8: return 'Backspace'; case 9: return 'Tab'; case 27: return 'Escape'; case 37: return 'ArrowLeft'; case 39: return 'ArrowRight'; case 188: return ','; case 190: return '.'; case 109: return '-'; // minus in numbpad case 173: return '-'; // minus in alphabet keyboard in firefox case 189: return '-'; // minus in alphabet keyboard in chrome default: return String.fromCharCode(e.keyCode); } } } }
- 自定义小数点分隔符(点或逗号)
- 仅支持整数或整数和小数
- 仅支持正数或正数和负数
- 验证减号(-)在开头
- 支持鼠标粘贴(虽然有一些限制https://caniuse.com/#feat=clipboard)
- 支持 Mac 命令键
替换像“.33”和“33”这样的字符串。对于正确的版本:0.33 和 33.0
import { Directive, ElementRef, HostListener, Input } from '@angular/core'; @Directive({ selector: '[NumbersOnly]' }) export class NumbersOnly { @Input() allowDecimals: boolean = true; @Input() allowSign: boolean = false; @Input() decimalSeparator: string = '.'; previousValue: string = ''; // -------------------------------------- // Regular expressions integerUnsigned: string = '^[0-9]*$'; integerSigned: string = '^-?[0-9]+$'; decimalUnsigned: string = '^[0-9]+(.[0-9]+)?$'; decimalSigned: string = '^-?[0-9]+(.[0-9]+)?$'; /** * Class constructor * @param hostElement */ constructor(private hostElement: ElementRef) { } /** * Event handler for host's change event * @param e */ @HostListener('change', ['$event']) onChange(e) { this.validateValue(this.hostElement.nativeElement.value); } /** * Event handler for host's paste event * @param e */ @HostListener('paste', ['$event']) onPaste(e) { // get and validate data from clipboard let value = e.clipboardData.getData('text/plain'); this.validateValue(value); e.preventDefault(); } /** * Event handler for host's keydown event * @param event */ @HostListener('keydown', ['$event']) onKeyDown(e: KeyboardEvent) { let cursorPosition: number = e.target['selectionStart']; let originalValue: string = e.target['value']; let key: string = this.getName(e); let controlOrCommand = (e.ctrlKey === true || e.metaKey === true); let signExists = originalValue.includes('-'); let separatorExists = originalValue.includes(this.decimalSeparator); // allowed keys apart from numeric characters let allowedKeys = [ 'Backspace', 'ArrowLeft', 'ArrowRight', 'Escape', 'Tab' ]; // when decimals are allowed, add // decimal separator to allowed codes when // its position is not close to the the sign (-. and .-) let separatorIsCloseToSign = (signExists && cursorPosition <= 1); if (this.allowDecimals && !separatorIsCloseToSign && !separatorExists) { if (this.decimalSeparator == '.') allowedKeys.push('.'); else allowedKeys.push(','); } // when minus sign is allowed, add its // key to allowed key only when the // cursor is in the first position, and // first character is different from // decimal separator let firstCharacterIsSeparator = (originalValue.charAt(0) != this.decimalSeparator); if (this.allowSign && !signExists && firstCharacterIsSeparator && cursorPosition == 0) { allowedKeys.push('-'); } // allow some non-numeric characters if (allowedKeys.indexOf(key) != -1 || // Allow: Ctrl+A and Command+A (key == 'a' && controlOrCommand) || // Allow: Ctrl+C and Command+C (key == 'c' && controlOrCommand) || // Allow: Ctrl+V and Command+V (key == 'v' && controlOrCommand) || // Allow: Ctrl+X and Command+X (key == 'x' && controlOrCommand)) { // let it happen, don't do anything return; } // save value before keydown event this.previousValue = originalValue; // allow number characters only let isNumber = (new RegExp(this.integerUnsigned)).test(key); if (isNumber) return; else e.preventDefault(); } /** * Test whether value is a valid number or not * @param value */ validateValue(value: string): void { // choose the appropiate regular expression let regex: string; if (!this.allowDecimals && !this.allowSign) regex = this.integerUnsigned; if (!this.allowDecimals && this.allowSign) regex = this.integerSigned; if (this.allowDecimals && !this.allowSign) regex = this.decimalUnsigned; if (this.allowDecimals && this.allowSign) regex = this.decimalSigned; // when a numbers begins with a decimal separator, // fix it adding a zero in the beginning let firstCharacter = value.charAt(0); if (firstCharacter == this.decimalSeparator) value = 0 + value; // when a numbers ends with a decimal separator, // fix it adding a zero in the end let lastCharacter = value.charAt(value.length-1); if (lastCharacter == this.decimalSeparator) value = value + 0; // test number with regular expression, when // number is invalid, replace it with a zero let valid: boolean = (new RegExp(regex)).test(value); this.hostElement.nativeElement['value'] = valid ? value : 0; } /** * Get key's name * @param e */ getName(e): string { if (e.key) { return e.key; } else { // for old browsers if (e.keyCode && String.fromCharCode) { switch (e.keyCode) { case 8: return 'Backspace'; case 9: return 'Tab'; case 27: return 'Escape'; case 37: return 'ArrowLeft'; case 39: return 'ArrowRight'; case 188: return ','; case 190: return '.'; case 109: return '-'; // minus in numbpad case 173: return '-'; // minus in alphabet keyboard in firefox case 189: return '-'; // minus in alphabet keyboard in chrome default: return String.fromCharCode(e.keyCode); } } } }
Usage:
用法:
<input NumbersOnly
[allowDecimals]="true"
[allowSign]="true"
type="text">
回答by Ben Gulapa
A more concise solution. Try this directive.
更简洁的解决方案。试试这个指令。
Can also be used if you're using ReactiveForms.
如果您使用的是 ReactiveForms,也可以使用。
export class NumberOnlyDirective {
private el: NgControl;
constructor(private ngControl: NgControl) {
this.el = ngControl;
}
// Listen for the input event to also handle copy and paste.
@HostListener('input', ['$event.target.value'])
onInput(value: string) {
// Use NgControl patchValue to prevent the issue on validation
this.el.control.patchValue(value.replace(/[^0-9]/g, ''));
}
}
The use it on your inputs like this:
在您的输入上使用它,如下所示:
<input matInput formControlName="aNumberField" numberOnly>
回答by ketan pradhan
<input type="text" (keypress)="keyPress($event)">
keyPress(event: any) {
const pattern = /[0-9\+\-\ ]/;
let inputChar = String.fromCharCode(event.charCode);
if (event.keyCode != 8 && !pattern.test(inputChar)) {
event.preventDefault();
}
}
回答by Pardeep Jain
you can achive it like this
你可以这样实现
<input type="text" pInputText (keypress)="onlyNumberKey($event)" maxlength="3">
onlyNumberKey(event) {
return (event.charCode == 8 || event.charCode == 0) ? null : event.charCode >= 48 && event.charCode <= 57;
}
//for Decimal you can use this as
onlyDecimalNumberKey(event) {
let charCode = (event.which) ? event.which : event.keyCode;
if (charCode != 46 && charCode > 31
&& (charCode < 48 || charCode > 57))
return false;
return true;
}
hope this will help you.
希望这会帮助你。
回答by Zia Khan
You need to use type="number" instead text. You can also specify max and min numbers
您需要使用 type="number" 而不是 text。您还可以指定最大和最小数字
<input type="number" name="quantity" min="1" max="5">
回答by Aathreya
You could use regex:
您可以使用正则表达式:
<input type="text" (keypress)="numericOnly($event)">
numericOnly(event): boolean {
let patt = /^([0-9])$/;
let result = patt.test(event.key);
return result;
}
回答by Behnam Azimi
Use pattern
attribute for input like below:
使用pattern
属性输入如下:
<input type="text" pattern="[0-9]+" >