I have developed a directive called AllowOnlyNumbers
that is applied to input textboxes.
<input
[AllowOnlyNumbers]=true
[maxLength]= 'yearlyFieldMaxLength'
type="tel"
name="totalAnnualIncome"
formControlName="totalAnnualIncome"
[(ngModel)]="yearlyIncomeAmt"
(focus)="onFocusEnableToolTip('TotalAnnualIncome')"
(focusout)="onFocusOutDisableToolTip('TotalAnnualIncome')"
minlength="2"
autocomplete="off"/>
This straightforward directive empowers users to only input numbers in the textbox.
import { Directive, HostListener, Input } from '@angular/core';
@Directive({
selector: '[AllowOnlyNumbers]'
})
/**
* @method AllowOnlyNumbers
* @desc This directive limits keyboard entries to numbers exclusively.
* Users can enter digits and use backspace, tab, enter, escape, end, home, left, right, and delete keys.
* Usage: <input type = "text" [AllowOnlyNumbers] = true />
*/
export class AllowOnlyNumbers {
constructor() { }
@Input() AllowOnlyNumbers: boolean;
/**
* @method onKeyDown
* @desc It restricts keyboard entries to numbers only.
* @argument event
* @returns only digit inputs
*
*/
@HostListener('keydown', ['$event']) onKeyDown(event) {
const e = event as KeyboardEvent;
if (this.AllowOnlyNumbers) {
// Allow: 8=Backspace, 9=Tab, 13=CR, 27=ESC, 35=END, 36=HOME, 37=Left, 39=Right, 46=DEL
if ([8, 9, 13, 27, 35, 36, 37, 39, 46].indexOf(e.keyCode) !== -1) {
return;
}
// Ensure it's a number and stop the keypress
if ((e.shiftKey || (e.keyCode < 48 || e.keyCode > 57)) && (e.keyCode < 96 || e.keyCode > 105)) {
e.preventDefault();
}
}
}
}
When attempting to write a unit test case using Jasmine, I encounter an issue with setting the @Input() AllowOnlyNumbers
property as true, as it always remains undefined. Below is my unit test file. (Please note: Keydown event is triggered)
import {ComponentFixture, TestBed} from '@angular/core/testing';
import { AllowOnlyNumbers } from './allow-only-numbers.directive';
import { Component, DebugElement, NO_ERRORS_SCHEMA } from '@angular/core';
import { By } from '@angular/platform-browser';
@Component({
template: `<input [AllowOnlyNumbers]= true type="text" name="totalAnnualIncome" />`
})
// tslint:disable-next-line:no-unnecessary-class
class TestAllowOnlyNumbersComponent {
// allowNumbers = true;
}
fdescribe('Directive: AllowOnlyNumbers', () => {
let component: TestAllowOnlyNumbersComponent;
let fixture: ComponentFixture<TestAllowOnlyNumbersComponent>;
let inputEl: DebugElement;
let linkDes;
let routerLinks;
beforeEach(() => {
TestBed.configureTestingModule({
declarations: [TestAllowOnlyNumbersComponent, AllowOnlyNumbers],
schemas: [NO_ERRORS_SCHEMA]
});
fixture = TestBed.createComponent(TestAllowOnlyNumbersComponent);
component = fixture.componentInstance;
inputEl = fixture.debugElement.query(By.css('input[name="totalAnnualIncome"]'));
});
it('triggers keydown on input', () => {
inputEl.triggerEventHandler('keydown', {});
fixture.detectChanges();
expect(true).toBe(true);
});
});
For more information, I am referring to this resource. The challenge lies in setting the @Input() AllowOnlyNumbers
property to true, which constantly returns as undefined.