import { Directive, ElementRef, EventEmitter, HostListener, Input, OnInit, Output, } from '@angular/core'; import { fromEvent, } from 'rxjs'; import { debounceTime, distinctUntilChanged, map, } from 'rxjs/operators'; const _initEventAvailable: boolean = (() => { if (document.createEvent) { const testEvent = document.createEvent('Event'); if (testEvent.initEvent) { return true; } } return false; })(); @Directive({ selector: '[debounce-on-change]', }) export class DebounceOnChangeDirective implements OnInit { @Output() public onChange = new EventEmitter(); @Input('debounce-on-change') public delay: number = 1000; constructor( private _elementRef: ElementRef, ) {} @HostListener('keyup') public onKeyUp() { let changeEvent; !_initEventAvailable ? changeEvent = new Event('change') : ( changeEvent = document.createEvent('Event'), changeEvent.initEvent('change', false, false) ); this._elementRef.nativeElement.dispatchEvent(changeEvent); } public ngOnInit() { const element = this._elementRef.nativeElement; fromEvent( element, 'change', ).pipe( map(() => element.value), distinctUntilChanged(), debounceTime(this.delay), ).subscribe((data) => this.onChange.emit(data)); } }