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