Angular2-숫자 만 허용하는 입력 필드


87

Angular 2에서 알파벳 문자가 아닌 숫자 만 받아들이도록 입력 필드 (텍스트 상자)를 마스크하려면 어떻게해야합니까?

다음 HTML 입력이 있습니다.

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

위의 입력은 단순 텍스트 필드 또는 숫자 필드 (예 : 연도 표시)로 사용할 수있는 일반 텍스트 입력입니다.

Angular 2를 사용하여 동일한 입력 컨트롤을 사용하고 숫자 만 허용하도록이 필드에 일종의 필터 / 마스크를 적용하려면 어떻게해야합니까?

이것을 달성 할 수있는 다른 방법은 무엇입니까?

참고 : 입력 번호 유형을 사용하지 않고 텍스트 상자 만 사용하여이 작업을 수행해야합니다.


1
html 속성 만 사용할 수 있습니까? = 숫자 입력
inoabrian

@inoabrian 숫자 유형을 사용하지 않고 이것을 달성하고 싶습니다.
Aniruddha Pondhe

이것은 당신을 도울 수 있습니다 : stackoverflow.com/questions/39799436/…
chandan7

답변:


112

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

모듈의 선언 배열에 지시문을 작성하는 것을 잊지 마십시오.

정규식을 사용하면 여전히 기능 키가 필요합니다.

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

1
훌륭합니다. RegEx 패턴을 사용하여 동일한 결과를 얻을 수있는 방법이 있습니까?
Aniruddha Pondhe

3
복사-붙여 넣기를 허용하지 않습니다.
Shardul

단지 추가 @Shardul (e.keyCode == 86 && e.ctrlKey === true)조건, 복사 노력하고 있지만, 붙여 넣기가 작동하지 않는
알 - Mothafar

1
공백, 플러스 및 마이너스를 어떻게 추가합니까?
Zahidul Islam Ruhel


66

지시어를 원하지 않는 경우

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

component.html에서

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

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;

  }
}

34
이 접근 방식의 문제점은 키 이벤트가 사용자 붙여 넣기 또는 입력 필드를 자동으로 채우는 브라우저를 캡처하지 않는다는 것입니다. 그래서 이것은 좋지 않은 해결책입니다.
Darryn Hosking

30

나는 이것이 오래된 질문이라는 것을 알고 있지만 이것은 일반적인 기능이기 때문에 내가 만든 수정 사항을 공유하고 싶습니다.

  • 사용자 지정 소수점 구분 기호 (포인트 또는 쉼표)
  • 정수만 또는 정수 및 소수 지원
  • 양수 또는 양수 및 음수 만 지원
  • 마이너스 부호 (-)가 처음에 있는지 확인
  • 마우스 붙여 넣기 지원 ( 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);
                }
            }
        }
    }
    

용법:

 <input NumbersOnly
        [allowDecimals]="true"
        [allowSign]="true"
        type="text">

유효하지 않은 붙여 넣기에 0을 추가하지 않도록 validatevalue 메서드의 마지막 줄을 변경했습니다. if (valid) {this.hostElement.nativeElement [ 'value'] = value;}
Abdul Rehman은

드래그 앤 드롭 유효성 검사도 추가 할 수 있습니까? 또한 입력 필드 값이 선행 및 후행 소수점 구분 기호에 대해 0으로 채워진 값으로 변경되지만 값이 양방향 바인딩 변수에서 업데이트되지 않는다는 것을 알았습니다. 예 : [(NgModel)] = "myVariable", 여기에서 입력 필드에 .3을 입력하면 텍스트 입력의 값이 블러시 0.3으로 변경되지만 myVariable의 값은 여전히 ​​'.3'으로 유지됩니다.
Sushmit Sagar

삭제하고 입력이 누락 된 입력, 어쨌든 솔루션은 매우 좋다
올렉 본다 렌코

29

저는 @omeralper가 제공 한 답변을 기반으로하고 싶습니다. 제 생각에는 견고한 솔루션을위한 좋은 토대를 제공했습니다.

제가 제안하는 것은 최신 웹 표준을 갖춘 단순화 된 최신 버전입니다. event.keycode는 웹 표준에서 제거되었으며 향후 브라우저 업데이트는 더 이상 지원하지 않을 수 있습니다. 참조 https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/keyCode를

또한 방법

String.fromCharCode(e.keyCode);

다른 키보드 구성으로 인해 특정 키 코드가 다른 문자를 생성하기 때문에 사용자가 누르는 키와 관련된 keyCode가 사용자의 키보드에서 식별되는 예상 문자에 매핑된다는 것을 보장하지 않습니다. 이를 사용하면 식별하기 어려운 버그가 발생하고 특정 사용자의 기능을 쉽게 손상시킬 수 있습니다. 오히려 event.key 사용을 제안하고 있습니다. https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key 여기 문서를 참조하십시오.

또한 결과 출력이 유효한 10 진수 여야합니다. 즉, 숫자 1, 11.2, 5000.2341234는 허용되어야하지만 1.1.2 값은 허용되지 않아야합니다.

내 솔루션에서는 특히 사람들이 관련 필드에 원하지 않는 텍스트를 붙여 넣을 때 버그에 대한 창이 열리기 때문에 잘라 내기, 복사 및 붙여 넣기 기능을 제외하고 있습니다. 키업 처리기에서 정리 프로세스가 필요했습니다. 이 스레드의 범위가 아닙니다.

여기 제가 제안하는 해결책이 있습니다.

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

이것은 정말 흥미로운 접근 방식입니다. (e.keyCode == 67 && e.ctrlKey === true) ??와 같은 이전 방법에 의존하지 않고 복사 / 붙여 넣기 기능을 구현하는 방법에 대한 제안이 있습니까?
Ender2050

1
개인적으로 이것을 시도하지는 않았지만, 트리거되는 복사 / 붙여 넣기 이벤트도 마찬가지로들을 수 있습니다. 복사 / 붙여 넣기중인 데이터를 포함 하는 ClipboardEvent ( developer.mozilla.org/en-US/docs/Web/API/ClipboardEvent )를 생성합니다 . 유일한 단점은 아직 실험적이며 최신 브라우저에서만 지원
된다는 것입니다.

비슷한 접근 방식을 시도했지만 안타깝게도 모든 경우에 적용되는 것은 아닙니다. "next"변수는 누른 문자가 현재 입력 된 값의 끝으로 이동한다고 가정합니다. 항상 그런 것은 아닙니다. 예를 들어, 누군가 100을 입력 한 다음 앞에 1을 추가하여 1100으로 만들기로 결정한 경우입니다. "다음"변수가 올바르지 않습니다 (1001).
Carlos Rodriguez

'next'값은 입력 금액이 유효한 십진수인지 확인하는 데만 사용되므로 (값을 설정하지 않음) 끝에 추가해도 정규식 유효성 검사가 변경되지 않습니다.
JeanPaul A.

이 줄을 추가하여 입력 제어에 적용하고 싶습니다. <input myNumberOnly type = "text"id = "yourId">
Lrodriguez84

17

더 간결한 솔루션. 이 지시문을 시도하십시오.

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

다음과 같이 입력에 사용하십시오.

<input matInput formControlName="aNumberField" numberOnly>

1
이 솔루션이 작동하는 동안 모델 변경 이벤트를 두 번 트리거하지만 정규식을 사용하는 접근 방식이 옳다고 말했습니다. 여기에 모델 변경 이벤트를 두 번 발생하지 않는 버전이 있습니다. stackblitz.com/edit/…
ntziolis

ntziolis의 의견 : 지금까지 Ben Gulapa의 솔루션이 저에게 효과적입니다. 그러나 ntziolis가 언급 한 해결책은 그렇지 않습니다. 내가 틀렸다면 용서하십시오.하지만 적어도 나를 위해 stackblitz에 대한 위 링크의 코드 문제는 내가 입력 한 마지막 원치 않는 문자가 사용자 인터페이스에는 표시되지 않았지만 어떻게 든 얻은 것 같습니다. 내 구성 요소의 바운드 변수에 넣습니다. 마지막 원치 않는 캐릭터.
user2367418

내 의견을 계속하려면 Angular 7과 HMTL 입력 텍스트를 사용하여 두 문자로 제한됩니다.
user2367418

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

14

텍스트 대신 type = "number"를 사용해야합니다. 최대 및 최소 수를 지정할 수도 있습니다.

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

2
숫자 유형을 사용하지 않고 이것을 달성하고 싶습니다.
Aniruddha Pondhe

3
숫자 유형에 대한 지원은이 답변에 설명 된대로 여전히 버그가 많습니다. stackoverflow.com/a/14995890/1156185
Nicolas Forney

9
의 단점은 type="number"이 문자를 허용한다는 것이다 e과학적 표기법의 한 부분으로
user776686

12

당신은 이것을 이렇게 얻을 수 있습니다

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

이것이 당신을 도울 수 있기를 바랍니다.


이것에 대해 자세히 설명해 주시겠습니까? event.charCode == 8은 무엇을하고 있습니까?
bosari

10

정규식을 사용할 수 있습니다.

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

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

1
예, 도움이되지만 내 입력 필드에도 (.) decimal을 원합니다
rinku Choudhary

7

나는 이것이 많은 답변을 가지고 있음을 알고 있지만 다음을 처리해야했습니다 (완전히 지원하는 답변은 없었습니다).

  • 여러 줄에 대한 옵션으로 텍스트 영역 지원
  • 소수 또는 음수
  • 라인 당 최대 길이
  • 브라우저 간 지원 (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;
      }
    }
  }

}


4

지시문을 만들고 아래에 hostlistener를 추가하십시오.

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

잘못된 텍스트를 빈 텍스트로 바꿉니다. 이제 모든 키와 키 조합이 IE9까지 모든 브라우저에서 작동합니다.


char로 유형을 시작하면 char은 추가되지 않지만 모델 길이의 개수는 1이 걸립니다. 어떻게 해결합니까?. 또한 요소에 최대 길이가있는 경우 혼합 된 콘텐츠를 복사하여 붙여 넣으면 모델 수가 최대 길이가됩니다. 예를 들어, 최대 길이가 10이면 1238261jhgjh12987을 복사하여 입력에 붙여 넣으면 123816 만 추가되지만 모델의 길이는 10이 걸립니다. 어떤 해결책이 있습니까?
Satheesh Natarajan 2018

4

이를 수행하기 위해 다음과 같이 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까지가 아닌 문자)를 입력하려고하면 텍스트 상자에 아무 일도 일어나지 않는 것처럼 나타납니다.


4

JeanPaul A.와 rdanielmurphy에게 감사드립니다. 입력 필드를 숫자로만 제한하기위한 고유 한 사용자 지정 지시문을 만들었습니다. 또한 최대 및 최소 입력 속성이 추가되었습니다. 각도 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();
      }
    }
  }

}

HTML

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

4

최상의 답변을위한 최신 접근 방식 (사용되지 않는 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();
    }
}

1
굉장합니다! @Directive ({선택기 : "[inputNumericInput]"}) 내보내기 클래스 NumericInputDirective {@HostListener ()}
Nate

2
잘 작동합니다. 복사 붙여 넣기에서는 부작용 만 관찰됩니다. 외부 비 숫자 문자열의 복사 붙여 넣기를 허용합니다. 구글에서 더 나은 해결책을 발견하는 주소이 @의 stackblitz.com/edit/...
vinsinraw

4

임의의 RegExp 지시어

다음은 임의의 정규 표현식을 사용하고 사용자가 잘못된 값을 입력하도록 차단하는 작은 지시문 입니다.

숫자 만 마스킹하려면

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

안타깝게도 곡절 + 쓰고 싶은 내용을 스팸으로 보내이 솔루션을 속일 수 있습니다.
ProgFroz 2010 년

3

유효한 휴대폰 번호 패턴 패턴 ( '^ ((\ + 91-?) | 0)? [0-9] {10} $')

텍스트 상자에서 숫자 만 허용하는 패턴 pattern ( '[0-9] *')

특정 번호가있는 번호 만 허용하려면 두드려주세요. 예 : 핀 코드. 패턴 ( '^ [0-9] {5} $')


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

또는 : 2. HTML 파일에서 :

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

TS 파일에서 :

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

이 두 가지 솔루션이 작동합니다.


코드 블록을 사용하여 코드 조각의 형식을 지정하십시오.
YuS

2

간단한 지시문 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 해당 모델에 대한 값을 숫자로만 :

아래와 같이 :

편집 : 모델의 변경을 감지하고 입력 값을 업데이트하는 코드 추가

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

char로 유형을 시작하면 char은 추가되지 않지만 모델 길이의 수는 1이 걸립니다. 어떻게 해결합니까?
Satheesh Natarajan 2018

길이를 확인할 때 변경 전후에 지시문에서 0으로 유지됩니다. 어느 시점에서 그것이 하나라면 그것은 빨리 0으로 돌아와야합니다.
Lahar Shah

아니에요. 그냥 템플릿에 numModel.length를 결합하려고 길이 카운트 확인
Satheesh Natarajan를

2

위의 지시문을 약간 수정하고 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();
    }

  }
}

입력 필드에서 최대 길이 값을 제공하는 방법
Jason Brody

<input id = "COMN"class = "wb-e-inp-1__input"type = "text"appNumberOnly maxlength = "10"/> 작동 중
Jason Brody

2

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

1

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

이 도움을 바랍니다 :)


1

이 유효성 검사기를 만들고 구성 요소로 가져올 수 있습니다.
기본적으로 양식 입력 문자열의 유효성을 검사합니다.

  • 점이 없는지 확인
  • 문자열을 숫자로 변환
  • 검사는 정수입니다.
  • 수표가 0보다 큼

프로젝트에서 구현하려면 :

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

하지 않음 Number.isInteger(Math.floor(control.value))항상 진실? parseFloat대신 해야한다고 생각합니다 .
AndyTheEntity 2018 년

1

붙여 넣은 콘텐츠 삭제 지원 :

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

}

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

      }
    }

지침은 또한이를 수행하는 가장 좋은 방법입니다.


0

fromCharCode는 숫자 키패드 '1'을 누르면 'a'를 반환하므로이 메 토이 드는 피해야합니다.

(관리자 : 평상시처럼 댓글을 달 수 없습니다)


0

복사 / 붙여 넣기 처리에 대한 댓글을 많이 보았습니다.

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

이렇게하면 숫자 인 경우에만 콘텐츠를 복사하여 텍스트 상자에 붙여 넣을 수 있습니다. 이것이 가장 간단한 해결책입니다. 숫자가 아닌 항목을 제거하기 위해 클립 보드의 내용을 변경하는 것은 훨씬 더 복잡하고 가치가 없을 수 있습니다.

IE에서 붙여 넣은 텍스트를 얻으려면 다음을 사용할 수 있습니다.

window.clipboardData.getData('Text');


0

쓰기에 충분하지 않을 것입니다

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

}


0

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

용법:

<input name="number" type="text" onlyNumber [(ngModel)]="someNumber">
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.