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

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

다음 HTML 입력이 있습니다.

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

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

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

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

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



답변

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


답변

지시어를 원하지 않는 경우

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;

  }
}


답변

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

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


답변

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


답변

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

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>


답변

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


답변

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

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