简体   繁体   English

Angular2 - 仅接受数字的输入字段

[英]Angular2 - Input Field To Accept Only Numbers

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.注意:我只需要使用文本框而不是使用输入数字类型来实现这一点。

You can use angular2 directives.您可以使用 angular2 指令。 Plunkr Plunkr

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

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在组件.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;

  }
}

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 )支持鼠标粘贴(虽然有一些限制https://caniuse.com/#feat=clipboard
  • Support for Mac command key支持 Mac 命令键
  • Replace strings like ".33" and "33."替换“.33”和“33”等字符串。 for the correct versions: 0.33 and 33.0对于正确的版本: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">

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.需要注意的是 event.keycode 已从 Web 标准中删除,未来的浏览器更新可能不再支持它。 See https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/keyCode请参阅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.不保证与用户按下的键相关的 keyCode 映射到用户键盘上标识的预期字母,因为不同的键盘配置将导致特定的 keycode 不同的字符。 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相反,我建议使用 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;这将需要在 keyup 处理程序上进行清理过程; which isn't the scope of this thread.这不是这个线程的范围。

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

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>

You need to use type="number" instead text.您需要使用 type="number" 代替文本。 You can also specify max and min numbers您还可以指定最大和最小数字

<input type="number" name="quantity" min="1" max="5">
<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();
    }
  }

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

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.希望这会帮助你。

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支持带有多行选项的 textarea
  • Decimals or negative numbers小数或负数
  • Max length per line每行最大长度
  • Cross-browser support (Chrome, Edge, IE 11)跨浏览器支持(Chrome、Edge、IE 11)
  • Handling cut/paste operations and events处理剪切/粘贴操作和事件

The solution allows me to define a textarea like this:该解决方案允许我像​​这样定义一个文本区域:

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

Or if I just want positive integers或者如果我只想要正整数

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

Here is my directive:这是我的指令:

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

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

or: 2. in The HTML File :或: 2. 在 HTML 文件中:

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

in The ts File:在 ts 文件中:

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

This 2 solution works这2个解决方案有效

Well Thanks to JeanPaul A. and rdanielmurphy.非常感谢 JeanPaul A. 和 rdanielmurphy。 I had made my own Custom directive for limiting input field to number only.我已经制定了自己的自定义指令,用于将输入字段仅限于数字。 Also added the max and min input attributes.还添加了最大和最小输入属性。 Will work in angular 7 also.也可以在角度 7 中工作。

Angular

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

}

HTML HTML

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

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

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

A modern approach for the best answer (without deprecated e.keyCode):最佳答案的现代方法(不推荐使用 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();
    }
}

Arbitrary RegExp directive任意 RegExp 指令

Here is small directive which use arbitrary regexp and block user to type invalid value这是使用任意正则表达式并阻止用户输入无效值的小指令

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

To mask only numbers use要仅屏蔽数字,请使用

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

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, '');
    }

Replace invalid text with empty.用空替换无效文本。 All keys and key combinations will now work across all browsers till IE9.现在,所有键和组合键都可以在所有浏览器中使用,直到 IE9。

In order to accomplish this, I bound a function to the onInput method like this:为了做到这一点,我将一个函数绑定到 onInput 方法,如下所示:

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

Here is the example inside my form:这是我的表单中的示例:

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

Then I added the following function to my component:然后我将以下函数添加到我的组件中:

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

This regex /[^0-9]/g searches for anything that is not a number and using .replace I set it to be replaced by nothing.这个正则表达式/[^0-9]/g搜索任何不是数字的东西,并使用.replace我将它设置为什么都不替换。 So when a user tries to type in a character that is not a number (in this case a character that is not zero through nine), it appears as if nothing happens in the text box.因此,当用户尝试输入一个不是数字的字符(在本例中是一个不是 0 到 9 的字符)时,文本框中似乎什么也没有发生。

Here is easy one: Simple directive On keydown event it checks the length of a key is one and key is not a number to preventDefault() and it won't renders that char.这是一个简单的指令: 简单指令 在 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: HTML:

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

Limitations: It will allow pasting using a mouse that way will accept other char.限制:它将允许使用鼠标粘贴,这样可以接受其他字符。 To avoid that you can pass the model as input to the directive and ngOnChage to that model change value to only numbers:为避免这种情况,您可以将模型作为输入传递给指令,并将ngOnChage给该模型,将值更改为仅数字:

Like below:如下所示:

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: HTML:

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

Pattern for the Valid Mobile number pattern('^((\+91-?)|0)?[0-9]{10}$')有效手机号码模式的模式('^((\+91-?)|0)?[0-9]{10}$')

Pattern for accept only number from text box pattern('[0-9]*')仅接受文本框模式中的数字的模式('[0-9]*')

patter for accept only number with specific number eg: Pincode.模式只接受具有特定号码的号码,例如:Pincode。 pattern('^[0-9]{5}$')模式('^[0-9]{5}$')

You can do this easily using a mask:您可以使用掩码轻松完成此操作:

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

99 - optional 2 digits 99 - 可选 2 位数

Don't forget to import NgxMaskModule in your module:不要忘记在你的模块中导入 NgxMaskModule:

imports: [
    NgxMaskModule.forRoot(),
]

I have made some modifications in the above directive and implemented min, max, maxlength.我对上述指令进行了一些修改,并实现了 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();
    }

  }
}

You could also create a directive which implements the ControlValueAccessor Interface ( https://angular.io/api/forms/ControlValueAccessor ).您还可以创建一个实现 ControlValueAccessor 接口 ( https://angular.io/api/forms/ControlValueAccessor ) 的指令。

See working example here: https://stackblitz.com/edit/angular-input-field-to-accept-only-numbers请参阅此处的工作示例: https ://stackblitz.com/edit/angular-input-field-to-accept-only-numbers

You can listen to the 'input' event and there is no need to check for keycodes.您可以收听“输入”事件,无需检查键码。 It supports copy & paste and integrates nicely with the Angular Forms API due to the ControlValueAccessor Interface.由于 ControlValueAccessor 接口,它支持复制和粘贴,并与 Angular Forms API 很好地集成。

Directive:指示:

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

Casting because it works also with leading 0 like 00345铸造,因为它也适用于前导 0,如 00345

@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, ''));
  }
}

from @omeralper 's answer.来自@omeralper 的回答。 I change a little bit that won't accept period ascii (keycode 110,190).我稍作改动,不接受句号 ascii(键码 110,190)。 and use let ch = (e.key);并使用 let ch = (e.key); to compare with regular expression when you change language (such as Thai or Japanese language) it won't accept character of those language当您更改语言(例如泰语或日语)时与正则表达式进行比较,它不会接受那些语言的字符

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

hope this help :)希望这有帮助:)

You can create this Validator and import it in your component.您可以创建此验证器并将其导入您的组件中。
Basically validates the form input string:基本上验证表单输入字符串:

  • check there is no dot检查没有点
  • converts string to number将字符串转换为数字
  • check is an integer检查是一个整数
  • check is greater than zero检查大于零

To implement it in your project:要在您的项目中实现它:

  1. suggested path in your app folder: src/app/validators/number.validator.ts应用文件夹中的建议路径:src/app/validators/number.validator.ts
  2. import in your component在您的组件中导入

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

  3. add it to the form control将其添加到表单控件
    inputNumber: ['', [NumberValidator.isInteger]],
  4. if you dont want to show the invalid char, bind a (change)="deleteCharIfInvalid()" to the input, if form.get('inputNumber').hasError('isInteger') is true , delete the last char inserted.如果您不想显示无效字符, (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;
    }        
}

With support for sanitizing pasted content:支持清理粘贴的内容:

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

}

只需在文本上使用类型编号,如下所示:

<input type="number" class="form-control" matInput name="value" placeholder="xxx" (change)="xxx()" formControlName="value">
 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();
          }
        };

      }
    }

Directive is also a best way to do it指令也是最好的方法

While there are more than a few answers, none comes as a simple npm package虽然有很多答案,但没有一个是简单的 npm 包

Based on Elvis Fernandez's answer, and after i added handling for a couple of edge cases I created an NG module that you can easly install using npm:基于Elvis Fernandez 的回答,在我添加了对几个边缘情况的处理之后,我创建了一个 NG 模块,您可以使用 npm 轻松安装:

npm i ngx-numbers-only-directive npm i ngx-numbers-only-directive

How To Use:如何使用:

In your appModule Import NgxNumbersOnlyDirectiveModule:在你的 appModule 中导入 NgxNumbersOnlyDirectiveModule:

import { NgxNumbersOnlyDirectiveModule } from 'ngx-numbers-only-directive'从 'ngx-numbers-only-directive' 导入 { NgxNumbersOnlyDirectiveModule }

and add it to your imports array:并将其添加到您的导入数组中:

imports: [NgxNumbersOnlyDirectiveModule]进口:[NgxNumbersOnlyDirectiveModule]

Add the directive to an input element.将指令添加到输入元素。 examples:例子:

< input NgxNumbersOnly > < 输入 NgxNumbersOnly >

To allow Negative numbers:允许负数:

<input NgxNumbersOnly [allowSign]=true> <输入 NgxNumbersOnly [allowSign]=true>

To allow decimals:允许小数:

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

if you do not wish to add the package, the directive source code is at :如果您不想添加包,指令源代码位于:

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

fromCharCode returns 'a' when pressing on the numpad '1' so this methoid should be avoided按下小键盘“1”时,fromCharCode 返回“a”,因此应避免使用此方法

(admin: could not comment as usual) (管理员:无法像往常一样发表评论)

I saw a lot of comments about handling copy/pasting.我看到很多关于处理复制/粘贴的评论。

To piggy back off of @omeralper answer, you can add a paste event handler to the onlyNumber directive to handle copy/pasting:要背负@omeralper 的答案,您可以将 paste 事件处理程序添加到 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.更改剪贴板的内容以删除非数字要复杂得多,而且可能不值得。

To get pasted text from IE you can use the following:要从 IE 中获取粘贴的文本,您可以使用以下命令:

window.clipboardData.getData('Text');

If you use primeng and Angular 6 or above there is the p-inputMask component.如果您使用 primeng 和 Angular 6 或更高版本,则有 p-inputMask 组件。 It prevents alpha typing AND negative values https://www.primefaces.org/primeng/#/inputmask它可以防止 alpha 类型和负值https://www.primefaces.org/primeng/#/inputmask

Would not be simple enough just to write写起来还不够简单

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

} }

<input type="number" min="0" oninput="this.value = Math.abs(this.value)">

HTML: HTML:

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

TS: 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 = '';

    }

  }

Ngx Mask has a great solution. Ngx Mask 有一个很好的解决方案。 It's a light package to install so it is worth it.这是一个轻量级的安装包,所以值得。 I use this when using type="number" is not a desired option.当使用 type="number" 不是所需的选项时,我会使用它。 Once installed all you have to do is: <input type="text" mask="separator.2" thousandSeparator="," />安装后,您所要做的就是: <input type="text" mask="separator.2" thousandSeparator="," />

You could use @ngneat/input-mask你可以使用@ngneat/input-mask

It is easy like that:这很容易:

TypeScript:打字稿:

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

Template:模板:

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

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

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

In HTML:在 HTML 中:

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

Angular2:角2:

    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 need to write the directive name in your input as an attribute.并且需要在您的输入中写入指令名称作为属性。

<input OnlyNumber="true" />

Below is my angular code that allows the only number to enter and only paste number, not text.下面是我的角度代码,它只允许输入数字并且只能粘贴数字,而不是文本。

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

And in ts file added in ngOnIt.并在 ngOnIt 中添加的 ts 文件中。

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

I used setTimeout for waiting time to load DOM.我使用 setTimeout 等待加载 DOM 的时间。 And used jquery with javascript to perform this task.并使用带有 javascript 的 jquery 来执行此任务。 'Paste' and 'keyup' are used to trigger paste and enter in the field. 'Paste' 和 'keyup' 用于触发粘贴并在字段中输入。

只需使用 HTML5,输入 type=”number”

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM