Search code examples
angulartypescriptrxjsevent-handling

Angular Emit event only if method does not get called for a certain timespan


I have an input field that calls the method inputChanged as soon as the input changes. It looks like this:

<custom-input (altered)="inputChanged($event)"
              ...
              >
@Output()
public changed: EventEmitter<string> = new EventEmitter();

...

public inputChanged(value: string): void {
    this.changed.emit(value + ...)
}

What I am trying to achieve is to only trigger this.changed.emit(value + ...) if the last time inputChanged has been called is more than 1000ms ago.

So the sequence could look like this.

inputChanged('t') -> 100ms -> inputChanged('te') -> 200ms -> inputChanged('tes') -> 50ms -> inputChanged('test') -> 1000ms -> this.changed.emit(value + ...)

I have found stuff like debounceTime in rxjs but I don't know how to use this in my context as I am not allowed to alter the input field compoment itself. The implementation has to be in the component that uses the input field.

Can anybody help me here?

FYI: I am using Angular 15.


Solution

  • Fun fact: a regular Observable can be used as an @Output() instead of an EventEmitter.

    In your component, introduce a Subject to push values through, then expose an Observable that uses debounceTime to control emissions.

    class YourComponent {
    
      private value$ = new Subject();
    
      @Output() changed = this.value$.pipe(debounceTime(1000));
    
      public inputChanged(value: string): void {
          this.value$.next(value + ...)
      }
    
    }
    

    Here's a little StackBlitz demo.