Angular Directives
In Angular, Directives are custom HTML attributes which tell Angular compiler to change the style or behavior of the elements. These are basically classes, that add additional behavior to elements in your Angular applications.
We have 3 different types of Directives in Angular
- Component Directives: These are directives with a template. General components
- Attribute Directives: These will change the appearance and behavior of the elements. Built in Attribute directives are NgClass, NgStyle, NgModel etc.
- Structural Directives: These will change the DOM layout by adding or removing DOM elements. Built in Attribute directives are NgIf, NgFor, NgSwitch etc.
You can read more about directives here.
Creating Numbers only Directive
ng generate directive numbersOnly
import { Directive } from '@angular/core'; @Directive({ selector: '[appNumbersOnly]' }) export class NumbersOnlyDirective { constructor() { } }app.module.ts
import { BrowserModule } from '@angular/platform-browser'; import { NgModule } from '@angular/core'; import { AppRoutingModule } from './app-routing.module'; import { AppComponent } from './app.component'; import { NumbersOnlyDirective } from './numbers-only.directive'; @NgModule({ declarations: [ AppComponent, NumbersOnlyDirective ], imports: [ BrowserModule, AppRoutingModule ], providers: [], bootstrap: [AppComponent] }) export class AppModule { }
import { Directive, ElementRef } from '@angular/core'; @Directive({ selector: '[appNumbersOnly]' }) export class NumbersOnlyDirective { inputElement: HTMLElement; constructor(public el: ElementRef) { this.inputElement = el.nativeElement; } }
@HostListener('keydown', ['$event']) onKeyDown(e: KeyboardEvent) { // Ensure that it is a number and stop the keypress if (!isNaN(+e.key)) { return; } else { e.preventDefault(); } } @HostListener('paste', ['$event']) onPaste(event:any) { event.preventDefault(); const pastedInput: string = event.clipboardData .getData('text/plain') .replace(/[^0-9-]+/ig, ''); // 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(/[^0-9-]+/ig, ''); this.inputElement.focus(); document.execCommand('insertText', false, textData); }
private navigationKeys = [ 'Backspace', 'Delete', 'Tab', 'Escape', 'Enter', 'Home', 'End', 'ArrowLeft', 'ArrowRight', 'Clear', 'Copy', 'Paste' ]; @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 (!isNaN(+e.key)) { return; } else { e.preventDefault(); } }
import { Directive, ElementRef, HostListener } from '@angular/core'; @Directive({ selector: '[appNumbersOnly]' }) export class NumbersOnlyDirective { 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 (!isNaN(+e.key)) { return; } else { e.preventDefault(); } } @HostListener('paste', ['$event']) onPaste(event:any) { event.preventDefault(); const pastedInput: string = event.clipboardData .getData('text/plain') .replace(/[^0-9-]+/ig, ''); // 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(/[^0-9-]+/ig, ''); this.inputElement.focus(); document.execCommand('insertText', false, textData); } }
Applying our custom attribute directive
Enter number: