Issue
While I was researching how to best do the digits only directive on the internet, I found the following result close to my own solution:
import { Directive, ElementRef, HostListener } from '@angular/core';
@Directive({
selector: '[appOnlyDigits]'
})
export class OnlyDigitsDirective {
private navigationKeys = [
'Backspace',
'Delete',
'Tab',
'Escape',
'Enter',
'Home',
'End',
'ArrowLeft',
'ArrowRight',
'Clear',
'Copy',
'Paste'
];
inputElement: HTMLElement;
constructor(public el: ElementRef) {
this.inputElement = el.nativeElement;
}
@HostListener('keydown', ['$event'])
onKeyDown(e: KeyboardEvent) {
if (
this.navigationKeys.indexOf(e.key) > -1 || // Allow: navigation keys: backspace, delete, arrows etc.
(e.key === 'a' && e.ctrlKey === true) || // Allow: Ctrl+A
(e.key === 'c' && e.ctrlKey === true) || // Allow: Ctrl+C
(e.key === 'v' && e.ctrlKey === true) || // Allow: Ctrl+V
(e.key === 'x' && e.ctrlKey === true) || // Allow: Ctrl+X
(e.key === 'a' && e.metaKey === true) || // Allow: Cmd+A (Mac)
(e.key === 'c' && e.metaKey === true) || // Allow: Cmd+C (Mac)
(e.key === 'v' && e.metaKey === true) || // Allow: Cmd+V (Mac)
(e.key === 'x' && e.metaKey === true) // Allow: Cmd+X (Mac)
) {
// let it happen, don't do anything.
return;
}
// Ensure that it is a number and stop the keypress.
if (
(e.shiftKey || (e.key < '0' || e.key > '9')) &&
(e.key < 'numpad 0' || e.key > 'numpad 9')
) {
e.preventDefault();
}
}
@HostListener('paste', ['$event'])
onPaste(event: ClipboardEvent) {
event.preventDefault();
const pastedInput: string = event.clipboardData!
.getData('text/plain')
.replace(/\D/g, ''); // get a digit-only string
document.execCommand('insertText', false, pastedInput);
}
@HostListener('drop', ['$event'])
onDrop(event: DragEvent) {
event.preventDefault();
const textData = event.dataTransfer!.getData('text').replace(/\D/g, '');
this.inputElement.focus();
document.execCommand('insertText', false, textData);
}
}
But when I press Shift+3 twice in a row, it allows typing '^' character. And sometimes it also writes the '+' character.
How can I fix this problem without changing the directive structure?
Solution
Try this one, I'm using it in my ongoing project works perfectly.
import { Directive, HostListener, Input, ElementRef } from '@angular/core';
@Directive({
selector: '[appNumbersOnly]'
})
export class OnlyNumbersDirective {
constructor(private el: ElementRef) { }
@Input() allowMultiLine = false;
@Input() allowNegative = false;
@Input() allowDecimal = false;
@Input() maxLength = 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 = ( window as any).clipboardData && ( window as any).clipboardData.getData('Text') // If IE, use window
|| ( event as ClipboardEvent) && ( event as ClipboardEvent).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) {
// tslint:disable-next-line: no-eval
this.regex = ( eval('/^'
+ (this.allowNegative ? '-?' : '')
+ (this.allowDecimal ? '((\\d+\\.?)|(\\.?))\\d*' : '\\d*')
+ '$/g') as RegExp);
}
const lines = this.allowMultiLine ? newValue.split('\n') : [newValue];
for (const line of lines) {
const lineText = line.replace('\r', '');
if (this.maxLength && lineText.length > this.maxLength || !lineText.match(this.regex)) {
event.preventDefault();
return;
}
}
}
}
Answered By - Manish Patidar
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.