Правильный способ ограничения значений ввода текста (например, только цифры)
Можно ли реализовать input
который позволяет вводить только цифры внутри без ручной обработки event.target.value
?
В React можно определить свойство value
после чего изменение ввода будет в основном связано со значением (его невозможно изменить без изменения value
). Смотрите пример. И это работает просто отлично без каких-либо усилий.
В Angular 2 можно определить [value]
, но он просто установит значение изначально, а затем input
не будет предотвращен от изменений.
Я играл с ngModel
и [value]/(input)
, см. Пример.
Но в обеих реализациях есть существенная проблема:
- при вводе 10 (значение модели 10; значение ввода 10) - правильно
- при последующем наборе 10d (значение модели 10 - не изменено, все нецифровые символы удалены; входное значение 10d) - неверно, поскольку значение модели такое же, как и раньше
- при вводе 10d3 - (значение модели 103; значение ввода 103) - правильно
Как сделать этот простой (с первого взгляда) компонент без ручной обработки event.target.value
?...
ОБНОВЛЕНИЕ Я не ищу нативный HTML5 элемент input[number]
здесь. Ввод чисел здесь только для примера - может быть гораздо больше задач, когда мне нужно ограничить ввод текста.
Более того, input[number]
равен 1) не ограничивает меня от ввода 10ddd
и 2) (менее важно) содержит стрелки, которые мне не нужны.
И проблема здесь состоит в том, чтобы запретить пользователю вводить что-то за пределами ограниченных значений, вместо того, чтобы позволять вводить что-либо и проверять это впоследствии
Ответы
Ответ 1
В component.ts добавь эту функцию
_keyUp(event: any) {
const pattern = /[0-9\+\-\ ]/;
let inputChar = String.fromCharCode(event.charCode);
if (!pattern.test(inputChar)) {
// invalid character, prevent input
event.preventDefault();
}
}
В вашем шаблоне используйте следующее
<input(keyup)="_keyUp($event)">
Это перехватит ввод до того, как angular2 отловит событие.
Ответ 2
Плагин inputmask делает лучшую работу в этом. Он чрезвычайно гибок в том смысле, что вы можете использовать любое регулярное выражение для ограничения ввода. Это также не требует JQuery.
Шаг 1: Установите плагин:
npm install --save inputmask
Шаг 2: создайте директиву для переноса маски ввода:
import {Directive, ElementRef, Input} from '@angular/core';
import * as Inputmask from 'inputmask';
@Directive({
selector: '[app-restrict-input]',
})
export class RestrictInputDirective {
// map of some of the regex strings I'm using (TODO: add your own)
private regexMap = {
integer: '^[0-9]*$',
float: '^[+-]?([0-9]*[.])?[0-9]+$',
words: '([A-z]*\\s)*',
point25: '^\-?[0-9]*(?:\\.25|\\.50|\\.75|)$'
};
constructor(private el: ElementRef) {}
@Input('app-restrict-input')
public set defineInputType(type: string) {
Inputmask({regex: this.regexMap[type], placeholder: ''})
.mask(this.el.nativeElement);
}
}
Шаг 3:
<input type="text" app-restrict-input="integer">
Проверьте их документы GitHub для получения дополнительной информации.
Ответ 3
После долгих исследований, наконец, я создаю функцию, которая полностью удовлетворяет требованиям. Функция, которую я создал, ограничивает все специальные символы и позволяет использовать только алфавиты и цифры... и эта функция отлично работает как для копирования, так и для ввода текста. Надеюсь, что это работает :)
public inputValidator(event: any) {
//console.log(event.target.value);
const pattern = /^[a-zA-Z0-9]*$/;
//let inputChar = String.fromCharCode(event.charCode)
if (!pattern.test(event.target.value)) {
event.target.value = event.target.value.replace(/[^a-zA-Z0-9]/g, "");
// invalid character, prevent input
}
}
<input type="text" [(ngModel)]="abc.abc" (input)="inputValidator($event)" />
Как вы используете -
1) Добавьте указанный выше метод в ваш компонент класса файла ts.
2) Вызвать метод inputValidator ($ event) для события ввода.
Ответ 4
Вы можете использовать ввод HTML5 номера типа
Он не принимает никаких символов в объявлении
<input type="number" [(model)]='myvar' min=0 max=100 step=5 />
Вот пример его использования с angular 2 [(model)]
http://www.webpackbin.com/VJNUNF0M-
Ответ 5
Протестировано Ответ:
form.html
<input type="text" (keypress)="restrictNumeric($event)">
form.component.ts:
public restrictNumeric(e) {
let input;
if (e.metaKey || e.ctrlKey) {
return true;
}
if (e.which === 32) {
return false;
}
if (e.which === 0) {
return true;
}
if (e.which < 33) {
return true;
}
input = String.fromCharCode(e.which);
return !!/[\d\s]/.test(input);
}
Ответ 6
Несколько ответов не работали для меня, поэтому я взял лучшие ответы на некоторые ответы (спасибо ребятам) и создал директиву Angular 5, которая должна выполнять работу (и многое другое) для вас. Возможно, это не идеально, но оно обеспечивает гибкость.
import { Directive, HostListener, ElementRef, Input, Renderer2 } from '@angular/core';
@Directive({
selector: '[appInputMask]'
})
export class InputMaskDirective {
@Input('appInputMask') inputType: string;
showMsg = false;
pattern: RegExp;
private regexMap = { // add your own
integer: /^[0-9 ]*$/g,
float: /^[+-]?([0-9]*[.])?[0-9]+$/g,
words: /([A-z]*\\s)*/g,
point25: /^\-?[0-9]*(?:\\.25|\\.50|\\.75|)$/g,
badBoys: /^[^{}*+£$%\\^-_]+$/g
};
constructor(public el: ElementRef, public renderer: Renderer2) { };
@HostListener('keypress', ['$event']) onInput(e) {
this.pattern = this.regexMap[this.inputType]
const inputChar = e.key;
this.pattern.lastIndex = 0; // dont know why but had to add this
if (this.pattern.test(inputChar)) {
// success
this.renderer.setStyle(this.el.nativeElement, 'color', 'green');
this.badBoyAlert('black');
} else {
this.badBoyAlert('black');
//do something her to indicate invalid character
this.renderer.setStyle(this.el.nativeElement, 'color', 'red');
e.preventDefault();
}
}
badBoyAlert(color: string) {
setTimeout(() => {
this.showMsg = true;
this.renderer.setStyle(this.el.nativeElement, 'color', color);
}, 2000)
}
}
HTML <input class="form-control" appInputMask="badBoys">
Ответ 7
Я думаю, что это решит вашу проблему. Я создал одну директиву, которая фильтрует ввод от пользователя и ограничивает количество или текст, который вы хотите.
Это решение предназначено для пользователей Ionic-3 и Angular -4.
import { Directive, HostListener, Input } from '@angular/core';
import { Platform } from 'ionic-angular';
/**
* Generated class for the AlphabateInputDirective directive.
*
* See https://angular.io/api/core/Directive for more info on Angular
* Directives.
*/
@Directive({
selector: '[keyboard-input-handler]' // Attribute selector
})
export class IonicKeyboardInputHandler {
@Input("type") inputType: string;
isNumeric: boolean = true;
str: string = "";
arr: any = [];
constructor(
public platForm: Platform
) {
console.log('Hello IonicKeyboardInputHandler Directive');
}
@HostListener('keyup', ['$event']) onInputStart(e) {
this.str = e.target.value + '';
this.arr = this.str.split('');
this.isNumeric = this.inputType == "number" ? true : false;
if(e.target.value.split('.').length === 2){
return false;
}
if(this.isNumeric){
e.target.value = parseInt(this.arr.filter( c => isFinite(c)).join(''));
}
else
e.target.value = this.arr.filter( c => !isFinite(c)).join('');
return true;
}
}
Ответ 8
<input type="number" onkeypress="return event.charCode >= 48 && event.charCode <= 57" ondragstart="return false;" ondrop="return false;">
Входные данные принимаются только цифры, но это только временное исправление.
Ответ 9
Я думаю, что оптимальным вариантом является ControlValueAccessor.
Не проверен, но, насколько я помню, это должно работать:
<input [(ngModel)]="value" pattern="[0-9]">
Забастовкa >
Ответ 10
Вот встроенный способ сделать это в angular 2:
<input onkeypress="return String.fromCharCode(event.charCode).match(/[a-zA-Z0-9 ]/g) != null">
Ответ 11
В Html
в поле ввода пишите:
(Нажатие) = "onlyNumberKey ($ событие)"
и в файле ts пишите:
onlyNumberKey (событие) { return (event.charCode == 8 || event.charCode == 0)? null: event.charCode >= 48 && event.charCode <= 57;
}
Ответ 12
Еще один
<form [formGroup]="myForm" novalidate>
<input type="text" class="form-control" id="data" name="data"
formControlName="input3" #item (input)="change(item.value)">
</form>
{{myForm.value |json}}
change(value:string)
{
let lastchar = value.substr(value.length - 1);
if (!(new RegExp('[0-9]').test(lastchar)))
{
value=value.substr(0,value.length-1);
this.myForm.controls["input3"].setValue(value);
}
}
если вы используете из ведомого шаблона
<input type="text" class="form-control" id="data" name="data"
[(ngModel)]="data" #item (input)="change(item)">
{{data}}
change(item:any)
{
let value=item.value;
let lastchar = value.substr(value.length - 1);
if (!(new RegExp('[0-9]').test(lastchar)))
{
value=value.substr(0,value.length-1);
item.value=this.data=value;
}
}
Обновление Как комментарий @BikashBishwokarma, это не сработает, если вы вставите символ посередине. Мы можем изменить функцию, например,
change(item:any)
{
let value=item.value;
let pos=item.selectionStart;
if (!(new RegExp('^[0-9]+$').test(value)))
{
item.value=this.data=value.replace(/[^0-9]+/g, '');
item.selectionStart = item.selectionEnd = pos-1;
}
}
Видите, как поддерживать позицию курсора
Ответ 13
В HTML:
<input (keypress)="onlyNumber(event)"/>
В компоненте:
onlyNumber(evt) {
evt = (evt) ? evt : window.event;
var charCode = (evt.which) ? evt.which : evt.keyCode;
if (charCode > 31 && (charCode < 48 || charCode > 57)) {
return false;
}
return true;
}
Ответ 14
Ниже приведено рабочее решение с использованием NgModel
Добавить переменную
public Phone:string;
В HTML добавить
<input class="input-width" [(ngModel)]="Phone" (keyup)="keyUpEvent($event)"
type="text" class="form-control" placeholder="Enter Mobile Number">
В ц файл
keyUpEvent(event: any) {
const pattern = /[0-9\+\-\ ]/;
let inputChar = String.fromCharCode(event.keyCode);
if (!pattern.test(inputChar)) {
// invalid character, prevent input
if(this.Phone.length>0)
{
this.Phone= this.Phone.substr(0,this.Phone.length-1);
}
}
}