Angular2-只接受数字的输入域

在角度2中,我如何掩盖一个输入字段(文本框) ,使它只接受数字,而不是字母字符?

我有以下 HTML 输入:

<input
type="text"
*ngSwitchDefault
class="form-control"
(change)="onInputChange()"
[(ngModel)]="config.Value"
(focus)="handleFocus($event)"
(blur)="handleBlur($event)"
/>

上面的输入是一个通用的文本输入,可以用作简单的文本字段,也可以用作数字字段,例如,用来显示年份。

使用角度2,我怎样才能使用相同的输入控制,并应用某种过滤器/掩码在这个领域,使它只接受数字?

有什么不同的方法可以实现这一点?

注意: 我需要实现这只使用文本框,而不使用输入数字类型。

374929 次浏览

您需要使用 type = “ number”代替 text。您还可以指定 max 和 min 数字

<input type="number" name="quantity" min="1" max="5">

可以使用 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();
}
}
}
}

并且需要在输入中将指令名作为属性写入

<input OnlyNumber="true" />

不要忘记在模块的声明数组中写入指令。

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();
}
}
}

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.

来自@omeralper 的回答。 我改变了一点,不会接受期间 ascii (键码110,190)。 并使用 let ch = (e.key) ; 与正则表达式进行比较,当您更改语言(如泰语或日语)时,它不会接受这些语言的字符

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) {
// console.log(event, this.OnlyNumber);
if ([46, 8, 9, 27, 13].indexOf(e.keyCode) !== -1) {
return;
}
let ch = (e.key);
let regEx =  new RegExp(this.regexStr);
if(regEx.test(ch))
return;
else
e.preventDefault();
}
}
}

希望这个能帮上忙:)

我想以@omeralper 给出的答案为基础,在我看来,它为一个坚实的解决方案提供了良好的基础。

我建议的是一个简化和最新的版本与最新的网络标准。值得注意的是,event.keycode 已经从 Web 标准中删除,未来的浏览器更新可能不再支持它。参见 https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/keyCode

此外,该方法

String.fromCharCode(e.keyCode);

不能保证与用户按下的键相关的 keyCode 映射到用户键盘上标识的预期字母,因为不同的键盘配置将导致特定的 keyCode 不同的字符。使用这种方法将引入难以识别的 bug,并且很容易破坏特定用户的功能。相反,我建议使用 event. key,请参阅这里的文档 https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key

此外,我们只希望结果输出是一个有效的小数。这意味着数字1.11.2,5000.2341234应该被接受,但是值1.1.2不应该被接受。

请注意,在我的解决方案,我排除剪切,复制和粘贴功能,因为它打开窗口的错误,特别是当人们粘贴不想要的文本在相关字段。这需要在一个 keyup 处理程序上执行一个清理过程; 这不是此线程的作用域。

这是我提出的解决方案。

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();
}
}
}

您可以创建这个 Validator 并将其导入到组件中。
Basically validates the form input string:

  • check there is no dot
  • 将字符串转换为数字
  • Check 是一个整数
  • check is greater than zero

在项目中实现它:

  1. 应用程序文件夹中的建议路径: src/app/validators/number.validator.ts
  2. 导入组件

    import { NumberValidator } from '../../validators/number.validator';

  3. 将其添加到窗体控件中
    inputNumber: ['', [NumberValidator.isInteger]],
  4. 如果不想显示无效的字符,请将 (change)="deleteCharIfInvalid()"绑定到输入,如果 form.get('inputNumber').hasError('isInteger')true,请删除插入的最后一个字符。
// FILE: src/app/validators/number.validator.ts


import { FormControl } from '@angular/forms';


export interface ValidationResult {
[key: string]: boolean;
}


export class NumberValidator {


public static isInteger(control: FormControl): ValidationResult {
// check if string has a dot
let hasDot:boolean = control.value.indexOf('.') >= 0 ? true : false;
// convert string to number
let number:number = Math.floor(control.value);
// get result of isInteger()
let integer:boolean = Number.isInteger(number);
// validate conditions
let valid:boolean = !hasDot && integer && number>0;
console.log('isInteger > valid', hasDot, number, valid);
if (!valid) {
return { isInteger: true };
}
return null;
}
}

Just Create a directive and add below hostlistener:

@HostListener('input', ['$event'])
onInput(event: Event) {
this.elementRef.nativeElement.value = (<HTMLInputElement>event.currentTarget).value.replace(/[^0-9]/g, '');
}

将无效的文本替换为空。所有的键和组合键现在可以在所有浏览器上工作,直到 IE9。

From CharCode 在按下 numpad’1’时返回‘ a’,因此应该避免使用这个方法

(管理员: 无法像往常一样发表评论)

为了实现这一点,我将一个函数绑定到 onInput 方法,如下所示:

(input)="stripText(infoForm.get('uin'))

下面是我表单中的例子:

<form [formGroup]="infoForm" (submit)="next()" class="ui form">
<input type="text" formControlName="uin" name="uin" id="uin" (input)="stripText(infoForm.get('uin'))" required/>
</form>

然后,我将以下函数添加到我的组件中:

  stripText(control: FormControl) {
control.setValue(control.value.replace(/[^0-9]/g, ''));
}

这个正则表达式 /[^0-9]/g搜索任何不是数字的内容,并使用 .replace将其设置为空值替换。因此,当用户试图输入一个不是数字的字符(在本例中是一个不是0到9的字符)时,文本框中似乎什么都没有发生。

<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();
}
}

对输入使用 pattern属性,如下所示:

<input type="text" pattern="[0-9]+" >

支持对粘贴内容进行消毒:

import { Directive, ElementRef, HostListener, Input } from '@angular/core';


@Directive({
selector: '[NumbersOnly]'
})
export class NumbersOnlyDirective {


DIGITS_REGEXP =  new RegExp(/\D/g);
constructor(private el: ElementRef) {


// Sanatize clipboard by removing any non-numeric input after pasting
this.el.nativeElement.onpaste = (e:any) => {
e.preventDefault();
let text;
let clp = (e.originalEvent || e).clipboardData;
if (clp === undefined || clp === null) {
text = (<any>window).clipboardData.getData('text') || '';
if (text !== '') {
text = text.replace(this.DIGITS_REGEXP, '');
if (window.getSelection) {
let newNode = document.createElement('span');
newNode.innerHTML = text;
window.getSelection().getRangeAt(0).insertNode(newNode);
} else {
(<any>window).selection.createRange().pasteHTML(text);
}
}
} else {
text = clp.getData('text/plain') || '';
if (text !== '') {
text = text.replace(this.DIGITS_REGEXP, '');
document.execCommand('insertText', false, text);
}
}
};
}


@HostListener('keydown', ['$event']) onKeyDown(event) {
let e = <KeyboardEvent> event;
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();
}
}


}

这里有一个简单的指令: 简单的指令 在 keydown 事件中,它检查键的长度是1,键不是 preventDefault()的数字,它不会呈现该字符。

import {Directive, ElementRef, HostListener} from '@angular/core';


@Directive({
selector: '[numbersOnly]'
})
export class NumbersOnlyDirective {
@HostListener('keydown', ['$event'])
keyDownEvent(event: KeyboardEvent) {
if (event.key.length === 1 && (event.which < 48 || event.which > 57)) {
event.preventDefault();
}
}


}

HTML:

<input type="text" [(ngModel)]="numModel" numbersOnly />

限制: 它将允许使用鼠标粘贴,这样将接受其他字符。为了避免这种情况,您可以将模型作为输入传递给指令,将 ngOnChage作为模型的输入,并将值更改为只有数字:

如下:

EDIT: Added Code to detect change in Model and update the input's value

import {Directive, ElementRef, HostListener, Input, OnChanges} from '@angular/core';


@Directive({
selector: '[numbersOnly]'
})
export class NumbersOnlyDirective implements OnChanges {


@Input() numbersOnly: any;


constructor(private el: ElementRef) {}


@HostListener('keydown', ['$event'])
keyDownEvent(event: KeyboardEvent) {
// Add other conditions if need to allow ctr+c || ctr+v
if (event.key.length === 1 && (event.which < 48 || event.which > 57)) {
event.preventDefault();
}
}


ngOnChanges(changes) {
if (changes.numbersOnly) {
this.el.nativeElement.value = this.el.nativeElement.value.replace(/[^0-9]/g, '');
}
}


}

HTML:

<input type="text" [(ngModel)]="numModel" [numbersOnly]="numModel" />

Use directive to restrict the user to enter only numbers in the following way:

.directive('onlyNumber', function () {
var regExp = /^[0-9]*$/;
return {
require: '?ngModel',
restrict: 'A',
priority: 1,
link: function (scope, elm, attrs, ctrl) {
ctrl.$validators.onlyNumber= function (modalValue) {
return ctrl.$isEmpty(modalValue) || regExp.test(modalValue);
};
}
};
})

HTML:

<input id="txtRollNumber" type="text" name="rollNumber" placeholder="Enter roll number*" ng-model="rollNumber" class="form-control" maxlength="100" required only-number />

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();
}
}
}
}

并且需要在您的输入中将指令名作为属性写入。

<input OnlyNumber="true" />

我看到很多关于处理复制/粘贴的评论。

要回答@omeralper 问题,您可以向 onlyNumber 指令添加一个粘贴事件处理程序来处理复制/粘贴:

 @HostListener('paste', ['$event']) onPaste(event) {
// Don't allow pasted text that contains non-numerics
var pastedText = (event.originalEvent || event).clipboardData.getData('text/plain');


if (pastedText) {
var regEx = new RegExp('^[0-9]*$');
if (!regEx.test(pastedText)) {
event.preventDefault();
}
}

This will only allow content to be copy and pasted into the textbox ONLY if it is a number. That's the simplest solution. Changing the content of the clipboard to remove non-numerics is a lot more complicated and might not be worth it.

要从 IE 中粘贴文本,可以使用以下方法:

window.clipboardData.getData('Text');

我在上面的指令中做了一些修改,并实现了 min,max,maxlength。

   import { Directive, ElementRef, HostListener, Input } from '@angular/core';


@Directive({
selector: '[numberOnly]'
})
export class NumbersOnlyDirective {


private regex: RegExp = new RegExp(/[0-9]/g);
// Allow key codes for special events. Reflect :
private specialKeys: Array<number> = [46, 8, 9, 27, 13, 110, 190, 35, 36, 37, 39];
// Backspace, tab, end, home


@Input() maxlength: number;
@Input() min: number;
@Input() max: number;


constructor(private el: ElementRef) {
}
@HostListener('keydown', ['$event'])
onKeyDown(event: KeyboardEvent) {
e = <KeyboardEvent>event;


if ((
(this.specialKeys.indexOf(event.which) > -1) ||
// to allow backspace, enter, escape, arrows
(e.which == 65 && e.ctrlKey == true) ||
// Allow: Ctrl+C
(e.which == 67 && e.ctrlKey == true) ||
// Allow: Ctrl+X
(e.which == 88 && e.ctrlKey == true))) {
return;
} else if (// to allow numbers
(e.which >= 48 && e.which <= 57) ||
// to allow numpad number
(event.which >= 96 && event.which <= 105)) { }
else {
event.preventDefault();
}
let current: string = this.el.nativeElement.value;


let next: string = current.concat(event.key);
if ((next && !String(next).match(this.regex)) ||
(this.maxlength && next.length > this.maxlength) ||
(this.min && +next < this.min) ||
(this.max && +next >= this.max)) {
event.preventDefault();
}


}
}

有效移动号码的模式 模式(’^ ((+ 91-?) | 0) ? [0-9]{10} $’)

只接受文本框中的数字的模式 pattern('[0-9]*')

只接受有特定号码的号码,例如: 平码。 模式(’^ [0-9]{5} $’)

如果你不想要指令

Https://stackblitz.com/edit/numeric-only

在组件中

<input (keypress)="numberOnly($event)" type="text">

在组件中

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;


}
}

一个更简洁的解决方案。

也可以在使用 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>

我知道这是一个老问题,但由于这是一个常见的功能,我想分享我所做的修改:

  • 自定义小数点(点或逗号)
  • 仅支持整数或整数和小数
  • 只支持正数或正数和负数
  • Validate minus sign(-) is in the beginning
  • 支持鼠标粘贴(虽然 https://caniuse.com/#feat=clipboard有一些限制)
  • 支持 Mac 命令键
  • 对于正确的版本: 0.33和33.0,将字符串替换为“ .33”和“33”

    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">

只要使用 HTML5,输入类型 = “数字”

你可以使用 regex:

<input type="text" (keypress)="numericOnly($event)">


numericOnly(event): boolean {
let patt = /^([0-9])$/;
let result = patt.test(event.key);
return result;
}

下面是我的角度代码,只允许数字输入,只粘贴数字,而不是文本。

<input id="pId" maxlength="8" minlength="8" type="text" [(ngModel)]="no" formControlName="prefmeno" name="no" class="form-control">

并在其文件中添加 ngOnIt。

ngOnInit() {
setTimeout(() => {
jQuery('#pId').on('paste keyup', function(e){
jQuery(this).val(document.getElementById('pId').value.replace(/[^\d]/g, ''));
});
}, 2000);
}

我使用 setTimeout 来等待加载 DOM 的时间,并使用 jquery 和 javascript 来执行这个任务。 'Paste' and 'keyup' are used to trigger paste and enter in the field.

多亏了 Jean Paul A 和 Rdanielmurphy。我制定了自己的自定义指令,将输入字段限制为只有数字。还添加了 max 和 min 输入属性。也将在角7工作。

角度

    import { Directive, ElementRef, Input, HostListener } from '@angular/core';


@Directive({
selector: '[appNumberOnly]'
})
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) { }


@Input() maxlength: number;
@Input() min: number;
@Input() max: number;


@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
const 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
const next: string = current.concat(event.key);
if (next && !String(next).match(this.regex) || (this.maxlength && next.length > this.maxlength) ||
(this.min && +next < this.min) ||
(this.max && +next >= this.max)) {
event.preventDefault();
}
}


@HostListener('paste', ['$event']) onPaste(event) {
// Don't allow pasted text that contains non-numerics
const pastedText = (event.originalEvent || event).clipboardData.getData('text/plain');


if (pastedText) {
const regEx = new RegExp('^[0-9]*$');
if (!regEx.test(pastedText) || (this.maxlength && pastedText.length > this.maxlength) ||
(this.min && +pastedText < this.min) ||
(this.max && +pastedText >= this.max)) {
event.preventDefault();
}
}
}


}

超文本标示语言

<input type="text" class="text-area" [(ngModel)]="itemName" maxlength="3" appNumberOnly />

只要在你的文本上使用类型号如下:

<input type="number" class="form-control" matInput name="value" placeholder="xxx" (change)="xxx()" formControlName="value">

如果您使用的启动和角度6或以上有 p-inputMask 组件。它可以防止键入 alpha 和负值 Https://www.primefaces.org/primeng/#/inputmask

光写字是不够简单的

onlyNumbers(event) {
if(isNaN(event.target.value * 1)) {
console.log("Not a number")
} else {
console.log("Number")
}

}

还可以创建实现 ControlValueAccessor 接口(https://angular.io/api/forms/ControlValueAccessor)的指令。

在这里看到工作例子: https://stackblitz.com/edit/angular-input-field-to-accept-only-numbers

你可以听“输入”事件,不需要检查键码。 由于 ControlValueAccessor 接口,它支持复制和粘贴,并与 Angular Forms API 很好地集成。

指令:

@Directive({
...
selector: '[onlyNumber]'
})
export class OnlyNumberDirective implements ControlValueAccessor {
private onChange: (val: string) => void;
...
private value: string;


constructor(
private elementRef: ElementRef,
private renderer: Renderer2
) {
}


...


@HostListener('input', ['$event.target.value'])
onInputChange(value: string) {
const filteredValue: string = filterValue(value);
this.updateTextInput(filteredValue, this.value !== filteredValue);
}


private updateTextInput(value, propagateChange) {
this.renderer.setProperty(this.elementRef.nativeElement, 'value', value);
if (propagateChange) {
this.onChange(value);
}
this.value = value;
}


// ControlValueAccessor Interface
...


registerOnChange(fn: any): void {
this.onChange = fn;
}


writeValue(value: string): void {
value = value ? String(value) : '';
this.updateTextInput(value, false);
}
}




function filterValue(value): string {
return value.replace(/[^0-9]*/g, '');
}

Usage:

<input name="number" type="text" onlyNumber [(ngModel)]="someNumber">
 import {Directive, ElementRef, HostListener, Output, EventEmitter} from '@angular/core';




//only-digits
@Directive({
selector: '[only-digits]'
})
export class OnlyDigits {


constructor(public el: ElementRef) {


this.el.nativeElement.onkeypress = (evt) => {
if (evt.which < 48 || evt.which > 57) {
evt.preventDefault();
}
};


}
}

指令也是最好的方法

I know this is has a lot of answers, but I needed to handle the following (which none of the answers seemed to fully support):

  • Support of textarea with option to for multi-lines
  • Decimals or negative numbers
  • 每行最大长度
  • Cross-browser support (Chrome, Edge, IE 11)
  • 处理剪切/粘贴操作和事件

这个解决方案允许我像这样定义一个文本区域:

<textarea class="form-control" [(ngModel)]="this.myModelVariable"
appOnlyNumbers [allowNegative]="true" [allowMultiLine]="true"
[allowDecimal]="true" [maxLength]="10"
placeholder="Enter values (one per line)"></textarea>

或者我只想要正整数

<textarea class="form-control" [(ngModel)]="this.myModelVariable"
appOnlyNumbers [allowMultiLine]="true" [maxLength]="9"
placeholder="Enter values (one per line)"></textarea>

以下是我的指示:

import { Directive, HostListener, Input, ElementRef } from '@angular/core';


@Directive({
selector: '[appOnlyNumbers]'
})
export class OnlyNumbersDirective {
constructor(private el: ElementRef) { }


@Input() allowMultiLine: boolean = false;
@Input() allowNegative: boolean = false;
@Input() allowDecimal: boolean = false;
@Input() maxLength: number = 0;
regex: RegExp;


@HostListener('keypress', ['$event'])
onKeyPress(event: KeyboardEvent) {
this.validate(event, event.key === 'Enter' ? '\n' : event.key);
}


@HostListener('paste', ['$event'])
onPaste(event: Event) {
const pastedText = (<any>window).clipboardData && (<any>window).clipboardData.getData('Text') // If IE, use window
|| <ClipboardEvent>event && (<ClipboardEvent>event).clipboardData.getData('text/plain'); // Non-IE browsers
this.validate(event, pastedText);
}


@HostListener('cut', ['$event'])
onCut(event: Event) {
this.validate(event, '');
}


validate(event: Event, text: string) {
const txtInput = this.el.nativeElement;
const newValue = (txtInput.value.substring(0, txtInput.selectionStart)
+ text + txtInput.value.substring(txtInput.selectionEnd));
if (!this.regex) {
this.regex = <RegExp>eval('/^'
+ (this.allowNegative ? '-?' : '')
+ (this.allowDecimal ? '((\\d+\\.?)|(\\.?))\\d*' : '\\d*')
+ '$/g');
}
var lines = this.allowMultiLine ? newValue.split('\n') : [newValue];
for (let line of lines) {
let lineText = line.replace('\r', '');
if (this.maxLength && lineText.length > this.maxLength || !lineText.match(this.regex)) {
event.preventDefault();
return;
}
}
}


}

一个最佳答案的现代方法(没有废弃的 e.keyCode) :

@HostListener('keydown', ['$event']) onKeyDown(event) {
let e = <KeyboardEvent> event;
if (['Delete', 'Backspace', 'Tab', 'Escape', 'Enter', 'NumLock', 'ArrowLeft', 'ArrowRight', 'End', 'Home', '.'].indexOf(e.key) !== -1 ||
// Allow: Ctrl+A
(e.key === 'a' && (e.ctrlKey || e.metaKey)) ||
// Allow: Ctrl+C
(e.key === 'c' && (e.ctrlKey || e.metaKey)) ||
// Allow: Ctrl+V
(e.key === 'v' && (e.ctrlKey || e.metaKey)) ||
// Allow: Ctrl+X
(e.key === 'x' && (e.ctrlKey || e.metaKey))) {
// let it happen, don't do anything
return;
}
// Ensure that it is a number and stop the keypress
if ((e.shiftKey || ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'].indexOf(e.key) === -1)) {
e.preventDefault();
}
}
<input type="number" min="0" oninput="this.value = Math.abs(this.value)">

任意 RegExp 指令

下面是小 directive,它使用任意 regexp 和块用户来键入无效值

import {Directive, HostListener, Input} from '@angular/core';


@Directive({selector: '[allowedRegExp]'})
export class AllowedRegExpDirective {
    

@Input() allowedRegExp: string;
  

@HostListener('keydown', ['$event']) onKeyDown(event: any) {
// case: selected text (by mouse) - replace it
let s= event.target.selectionStart;
let e= event.target.selectionEnd;
let k= event.target.value + event.key;
        

if(s!=e) {
k= event.target.value
k= k.slice(0,s) + event.key + k.slice(e,k.length);
}


// case: special characters (ignore)
if(['ArrowLeft','ArrowRight','ArrowUp','ArroDown','Backspace','Tab','Alt'
'Shift','Control','Enter','Delete','Meta'].includes(event.key)) return;


// case: normal situation - chceck regexp
let re = new RegExp(this.allowedRegExp);
        

if(!re.test(k)) event.preventDefault();
}
}

只用数字来掩盖

<input [allowedRegExp]="'^[0-9]*$'" type="text" ... >

Casting because it works also 像00345这样的0开头

@Directive({
selector: '[appOnlyDigits]'
})
export class AppOnlyDigitsDirective {
@HostListener('input', ['$event'])
onKeyDown(ev: KeyboardEvent) {
const input = ev.target as HTMLInputElement;
input.value = String(input.value.replace(/\D+/g, ''));
}
}

HTML:

<input type="text" maxlength="5"(focusout)="onTextboxFocusOutDecimalPercentageValidate($event)"
(input)="onTextboxChangeDecimalPercentageValidate($event)">

TS:

onTextboxChangeDecimalPercentageValidate(event: Event) {


var inputData = (<HTMLInputElement>event.target).value;


//replace more than one dot


var extractedFte = inputData.replace(/[^0-9.]/g, '').replace('.', 'x')


.replace(/\./g, '').replace('x', '.');


//Extract Decimal Values


extractedFte = extractedFte.replace(/^(\d+.?\d{0,2})\d*$/, "$1");


//Reasign to same control


(<HTMLInputElement>event.target).value = extractedFte;


if (extractedFte != '' && Number(extractedFte) >= 100) {


(<HTMLInputElement>event.target).value = '100'; extractedFte = '100';


}


// if (Number(extractedFte) == 0) {


//   (<HTMLInputElement>event.target).value = ''; extractedFte = '';


// }


}


onTextboxFocusOutDecimalPercentageValidate(event: Event) {


var inputData = (<HTMLInputElement>event.target).value;


//replace more than one dot


var extractedFte = inputData.replace(/[^0-9.]/g, '').replace('.', 'x')


.replace(/\./g, '').replace('x', '.');


//Extract Decimal Values


extractedFte = extractedFte.replace(/^(\d+.?\d{0,2})\d*$/, "$1");


//Reasign to same control


(<HTMLInputElement>event.target).value = extractedFte;


if (extractedFte != '' && Number(extractedFte) >= 100) {


(<HTMLInputElement>event.target).value = '100'; extractedFte = '100';


}


if (Number(extractedFte) == 0) {


(<HTMLInputElement>event.target).value = ''; extractedFte = '';


}


}
  1. <input oninput="this.value=this.value.replace(/[^0-9]/g,'')"

2. HTML 档案:

 <input [(ngModel)]="data" (keypress)="stripText($event)"
class="form-control">

文件:

stripText(event) {
const seperator  = '^([0-9])';
const maskSeperator =  new RegExp(seperator , 'g');
let result =maskSeperator.test(event.key);   return result;   }

这两个解决方案是有效的

你可以很容易地用一个面具做到这一点:

<input type='text' mask="99" formControlName="percentage" placeholder="0">

99-可选的2位数字

不要忘记在模块中导入 NgxMaskModule:

imports: [
NgxMaskModule.forRoot(),
]

虽然有很多答案,但没有一个是简单的 npm 包

基于 Elvis Fernandez 的的回答,在我添加了几个边缘案例的处理之后,我创建了一个 NG 模块,您可以使用 npm 轻松地安装它:

npm i ngx-numbers-only-directive

使用方法:

在 appModule 中导入 NgxNumbersOnly DirectiveModule:

导入{ NgxNumbersOnlyDirectiveModule }

并将其添加到导入数组中:

导入: [ NgxNumbersOnlyDirectiveModule ]

将该指令添加到一个 input 元素。示例:

< 输入 NgxNumbersOnly >

To allow Negative numbers:

< input NgxNumbersOnly [ allowSign ] = true >

允许小数:

< input NgxNumbersOnly [ allowDecimals ] = true [ allowSign ] = true >

如果您不希望添加包,则指令源代码位于:

https://github.com/abfist/NgxNumbersOnlyDirective/tree/master/projects/ngx-numbers-only-directive/src/lib

Ngx 面具有一个伟大的解决方案。这是一个轻量级的软件包安装,所以它是值得的。当使用 type = “ number”不是一个理想的选项时,我使用这种方法。 一旦安装完成,你需要做的就是: <input type="text" mask="separator.2" thousandSeparator="," />

你可以用 输入掩码

这很简单:

字体脚本:

onlyNumbersMask = createMask<string>({
regex: "\\d*",
});

Template:

<input[(ngModel)]="value" [inputMask]="onlyNumbersMask">

StackBlitz 演示: Https://stackblitz.com/edit/input-mask-only-numbers-ngneat-input-mask?file=src/app/app.component.ts