Reactive extensions (RxJS) provide a composable way to handle streams of asynchronous events. Using the debounce operator, we can delay a search action until the user stops typing — but rather than wiring this up on every component, a directive is the cleaner approach. Angular's guide recommends using directives to attach DOM events, which is exactly what this does.
The key advantage: by using a directive instead of a wrapper component, the native <input> element retains all its original functionality — no extra layers needed.
typescript
import { Directive, Input, Output, EventEmitter, HostListener } from '@angular/core';
import { Observable, Subject, interval } from 'rxjs';
import { debounce } from 'rxjs/operators';
@Directive({
selector: '[cxDebounceKeyUp]'
})
export class CxDebounceKeyUpDirective {
public NewEventSubject = new Subject<KeyboardEvent>();
public NewEvent: Observable<KeyboardEvent>;
@Input()
public Interval = 300;
@Output()
public DebouncedEvent = new EventEmitter<KeyboardEvent>();
@HostListener('keyup', ['$event'])
public OnKeyUp(ev: KeyboardEvent) {
this.NewEventSubject.next(ev);
}
constructor() {
this.NewEvent = this.NewEventSubject.pipe(debounce(() => interval(this.Interval)));
this.NewEvent.subscribe(value => {
this.DebouncedEvent.emit(value);
});
}
}Usage
xml
<input matInput cxDebounceKeyUp (DebouncedEvent)="applyFilter($event)" placeholder="Workspace name" #input />