Issue
I have an input:
<div class="col-md-2">
<input appElevenDigitInteger
name="NDC{{index}}"
class="form-control"
(paste)="handlePasteNDC($event.clipboardData.getData('text/plain'))"
(change)="ndcChanged($event, index)"
[(ngModel)]="model.NDC[index]"
#ndc="ngModel"
required
maxlength="11"
minlength="11">
<div class="text-danger"
*ngIf="ndc.invalid && (ndc.dirty || ndc.touched)">
<p *ngIf="ndc.errors.required">NDC is required.</p>
<p *ngIf="ndc.errors.minlength || ndc.errors.maxlength">NDC must be 11 digits.
</p>
</div>
</div>
That input is using a directive to only allow numeric input, although the input is a string (hence not using numeric input box). Here is the directive:
import { Directive, ElementRef, HostListener } from '@angular/core';
@Directive({
selector: '[appElevenDigitInteger]'
})
export class ElevenDigitIntegerDirective {
private regex: RegExp = new RegExp(/^\d{0,11}$/g);
private specialKeys: Array<string> = ['Backspace', 'Tab', 'End', 'Home', 'ArrowLeft', 'ArrowRight', 'Del', 'Delete'];
constructor(private el: ElementRef) {
}
@HostListener('keydown', ['$event']) onKeyDown(e: KeyboardEvent) {
if (this.specialKeys.indexOf(e.key) !== -1
|| (e.key === 'v' && e.ctrlKey === true)
|| (e.key === 'v' && e.metaKey === true)) {
return;
}
let current: string = this.el.nativeElement.value;
const startPosition = this.el.nativeElement.selectionStart;
const endPosition = this.el.nativeElement.selectionEnd;
const next: string = [current.slice(0, startPosition), e.key == 'Decimal' ? '.' : e.key, current.slice(endPosition)].join('');
if (next && !String(next).match(this.regex)) {
e.preventDefault();
}
}
@HostListener('paste', ['$event']) onPaste(e: ClipboardEvent) {
return;
}
}
I also have a paste function to check that the value matches an up to 11 digit numeric value. Here is that function:
handlePasteNDC(e) {
var regex = new RegExp(/^\d{0,11}$/g);
if (regex.test(e)) {
return true;
}
return false;
}
I need to be able to detect changes in the value of that variable, and if it is exactly 11 digits, call an API, looking up a drug name. Anything less than 11 digits, and the drug name should be null. I've added a (change)
event function, but that's obviously not being called because it is intercepted by the directive. Here is that function (for now):
ndcChanged(event: any, index: number){
console.log(index);
}
Given the directive that is ensuring only numeric input, how can I detect changes to the this.model.NDC[index]
variable? I want to check the string length every time it changes, and call the API when it is 11 characters.
OR - is there a way to keep the input only numeric, and allow paste (paste will be used most of the time because an 11 digit number goes into the form), but disallow letters, that doesn't preclude me from using the (change)
event? I know I'm probably way overthinking this. The reason I went the directive route is because I also needed another field to be limited to 2 digits past the decimal, and that directive works fine, so I made another to match, and changed the Regex string.
Thank you.
Solution
Given no suggestions here, I ended up using the keyup event. This works for every instance except for right-click paste. Since the application is used internally, we can train those who might use the mouse to copy/paste how to do it with keyboard shortcuts. Not a perfect solution, but it works.
Answered By - Rich Hopkins
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.