import { AfterViewInit, Directive, EventEmitter, Input, OnDestroy, Optional, Output } from '@angular/core'; import { NgModel } from '@angular/forms'; import { BooleanInput, InputBoolean, InputNumber, NumberInput } from '@delon/util'; import { Subscription } from 'rxjs'; import { debounceTime, distinctUntilChanged } from 'rxjs/operators'; @Directive({ selector: '[delay]:not([noDelay])', exportAs: 'delayComp' }) export class DelayDirective implements AfterViewInit, OnDestroy { static ngAcceptInputType_delayTime: NumberInput; static ngAcceptInputType_delayFirstEmit: BooleanInput; private data$: Subscription | undefined; private firstEmit = false; @Input() @InputNumber() delayTime = 500; @Input() @InputBoolean() delayFirstEmit = false; @Output() readonly delayChange = new EventEmitter(); constructor(@Optional() private ngModel: NgModel) {} ngAfterViewInit(): void { const { ngModel, delayFirstEmit, delayTime, delayChange } = this; if (ngModel == null) { return; } this.firstEmit = delayFirstEmit; this.data$ = ngModel.valueChanges?.pipe(debounceTime(delayTime), distinctUntilChanged()).subscribe(res => { if (this.firstEmit === false) { this.firstEmit = true; return; } delayChange.emit(res); }); } ngOnDestroy(): void { if (this.data$) { this.data$.unsubscribe(); } } }