Search code examples
angulartypescriptrxjsobservablesubscription

What is the correct way to do something immediately after a form changed and also with a delay in Angualr and RxJS?


I have a form in a component which should do two things when its values change:

  • update the view immediately
  • emit the form values to the parent after a short delay

A service in the parent component is going to send a new request to an API on form value change. This should not happen on every keystroke, to reduce requests. So I throttled emitting the event.

Unfortunately I have two subscribers now: One that handles the view update and a second with debounceTime that takes care of the EventEmitter:

private subscribeToChanges(): void {
  this.form.valueChanges.pipe(
    distinctUntilChanged(),
    takeUntil(this.isDestroyed$)
  ).subscribe(() => {
    this.updateView();
  });

  this.form.valueChanges.pipe(
    debounceTime(400),
    distinctUntilChanged(),
    takeUntil(this.isDestroyed$)
  ).subscribe(() => {
    this.changed.emit(this.form.value);
  });
}

I could add a timeout myself in the first subscriber, but this doesn't feel good as well.

What is the correct way of doing this?


Solution

  • You could try to use the tap operator and apply the debounceTime after the tap. Try the following

    private subscribeToChanges(): void {
      this.form.valueChanges.pipe(
        distinctUntilChanged(),
        takeUntil(this.isDestroyed$),
        tap(value => this.updateView()),
        debounceTime(400)
      ).subscribe(() => {
        this.changed.emit(this.form.value);
      });
    }