2017-01-04 3 views
18

В Angular2, как я могу маскировать поле ввода (текстовое поле) так, чтобы оно принимало только числа, а не алфавиты?Angular2 - Поле ввода для приема только чисел

У меня есть следующий HTML вход:

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

выше вход общий ввод текста, который может быть либо использован в качестве простого текстового поля или в виде числового поля, (например, чтобы показать год) ,

Использование углового2, как я могу использовать один и тот же элемент управления ввода и применить в этом поле какой-либо фильтр/маску, чтобы он принимал только числа? Каким образом я могу достичь этого?

Примечание: Мне нужно достичь этого, используя только текстовое поле и не используя тип входного номера.

+0

ли вы быть в состоянии использовать только атрибут HTML? type = number – inoabrian

+0

@inoabrian Я хочу достичь этого, не используя тип номера. –

+0

Это может помочь вам: http: // stackoverflow.com/questions/39799436/angular-2-custom-validator-check-if-the-input-value-is-integer – chandan7

ответ

3

Вам нужно использовать type = "number" вместо текста. Вы также можете указать максимальные и минимальные номера

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

Я хочу достичь этого без использования типа числа. –

+0

не работает с IE – keepscoding

+0

Поддержка типа номера по-прежнему довольно затруднительна, как описано в этом ответе: http://stackoverflow.com/a/14995890/1156185 –

50

Вы можете использовать директивы angular2. 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(); 
     } 
     } 
    } 
} 

и вам нужно написать директиву имя в качестве входного атрибута

<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? –

+0

@AniruddhaPondhe Я обновил ответ для регулярного выражения. – omeralper

+2

Не допускается копирование. – Shardul

7

вы можете achive его как этот

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

надеюсь, что это поможет вам.

+0

не могли бы вы рассказать об этом? что делает event.charCode == 8? – basari66

0

от ответа @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(); 
    } 
    } 
} 

надеюсь, что это поможет :)

19

Я хотел бы построить на ответ предоставленный компанией @omeralper, который, на мой взгляд, обеспечил хорошую основу для твердого решения.

Я предлагаю упрощенную и обновленную версию с последними веб-стандартами. Важно отметить, что код события.key удаляется из веб-стандартов, и будущие обновления браузера могут его больше не поддерживать. См https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/keyCode

Кроме того, метод

String.fromCharCode(e.keyCode); 

не гарантирует, что KEYCODE, относящиеся к ключу нажат с помощью пользовательских карт до ожидаемого письма, как указано на клавиатуре пользователя, так как различные конфигурации клавиатуры приведет в конкретном ключевом коде разные символы.Использование этого приведет к ошибкам, которые трудно идентифицировать, и может легко нарушить функциональность для определенных пользователей. Скорее я предлагаю использовать event.key, см. Здесь docs. https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key

Кроме того, мы хотим, чтобы результирующий результат был действительным десятичным. Это означает, что цифры 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(); 
     } 
    } 
} 
+0

Это действительно интересный подход. Есть ли у вас какие-либо предложения о том, как реализовать функции копирования/вставки без использования более старых методов, таких как (e.keyCode == 67 && e.ctrlKey === true)? – Ender2050

+1

Я лично не пробовал это, однако вы можете так же слушать события копирования/вставки, которые запускаются. Они генерируют ClipboardEvent (https://developer.mozilla.org/en-US/docs/Web/API/ClipboardEvent), который содержит данные, которые копируются/вставляются. Единственный недостаток заключается в том, что это все еще экспериментально и поддерживается только последними браузерами - https://caniuse.com/#search=paste –

+0

Я пробовал аналогичный подход, но, к сожалению, это не работает для каждого случая. Ваша «следующая» переменная предполагает, что нажатый символ идет в конце текущего введенного значения. Это не всегда так. Например, если кто-то набирает 100, а затем решает сделать это 1100, добавив 1 к фронту. Ваша «следующая» переменная будет неправильной (1001). –

0

Вы можете создать этот валидатор и импортировать его в свой компонент.
В основном проверяет формы входной строки:

  • чек там нет точки
  • преобразует строку на номер
  • проверка представляет собой целое число
  • проверка больше нуля

Для реализации это в вашем проекте:

  1. предложил путь в папку приложения: SRC/приложение/валидаторов/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; 
    }   
} 
+0

Не будет 'Number.isInteger (Math.floor (control.value))' всегда верно? Я думаю, что это должно быть 'parseFloat'. – AndyTheEntity

1

Просто Создайте директиву и добавьте ниже hostlistener:

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

Заменить недопустимый текст с пустыми. Все ключи и комбинации клавиш теперь будут работать во всех браузерах до IE9.

0

fromCharCode возвращает «а» при нажатии на цифровой клавиатуре «1», так это methoid следует избегать

(админ: не могли бы прокомментировать, как обычно)

2

Для того, чтобы достичь этого, я привязал функцию методу 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 я поставил его заменить ничем. Поэтому, когда пользователь пытается ввести символ, который не является числом (в этом случае символ, который не равен нулю до девяти), он выглядит так, как будто в текстовом поле ничего не происходит.

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

Используйте pattern атрибут для ввода, как показано ниже:

<input type="text" pattern="[0-9]+" > 
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(); 
     } 
    } 

} 
0

Здесь легко одна: Простая директива На KeyDown случае он проверяет длина ключа одна, а ключ не является числом до 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: Добавлен код для обнаружения изменения в модели и обновлять значение на вход в

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

Используйте директиву, чтобы ограничить пользователя введите только цифры следующим образом:

.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 /> 
Смежные вопросы