0

How could I use rxjs debounceTime and distinctUntilChanged with angular input events (input) or (click)

I can't use fromEvent because I also need to pass parameter (Example below)

<li *ngFor="let item of items>
 <input [(ngModel)]="item.name" (input)="inputChanged(item.id)">
</li>

So I went with Subject (Example below)

<input type="text" placeholder="Type something..." (input)="inputFn($event, 'myParam')"  #myInput>

@ViewChild("myInput", { static: true }) myInput;
private inputEvent = new Subject<any>();

ngOnInit() {
    this.inputEvent
      .pipe(
        // map((obj: any) => obj.evt.target.value),
        debounceTime(1000),
        distinctUntilChanged()
      )
      .subscribe(res => {
        console.log("res", res.evt.target.value);
      });
  }

  inputFn(evt, param) {
    this.inputEvent.next({evt, param});
  }

In the above example, there is no use of distinctUntilChanged(). If I filter with map map((obj: any) => obj.evt.target.value) and look for value change (distinct) I am going to get only input value not parameter.

My requirement is - I want to wait until user finished entering text and also if user re-enter want to check if value is not same as previous and also want to get parameter.

1 Answer 1

2

You have to use in distinctUntilChanged operator the compare function

import { Component, ViewChild, OnInit } from '@angular/core';
import { Subject } from 'rxjs';
import { debounceTime, distinctUntilChanged } from 'rxjs/operators';

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.css' ]
})
export class AppComponent implements OnInit {
  @ViewChild("myInput", { static: true }) myInput;
  private inputEvent = new Subject<any>();

  ngOnInit() {
    this.inputEvent
      .pipe(
        debounceTime(1000),
        distinctUntilChanged((previous: any, current: any) => previous.value === current.value)
      )
      .subscribe(res => {
        console.log("res", res.evt.target.value);
      });
  }

  inputFn(evt, param) {
    this.inputEvent.next({evt, param, value: evt.target.value});
  }
}

stackblitz

Sign up to request clarification or add additional context in comments.

2 Comments

It works for the first time only, If you enter any new text after previous one then no console log has been printed :(
I have updated the stackblitz, now it works fine. It worked only the first time because in the distinctUntilChanged the condition on the event.target.value was a fail, "previous" and the "current" have the same reference to the HTML input because it is an object and in consequence, have the same value in the condition. So I added property value in the object to get a primitive and now the operator can compare a real previous value and a real current value.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.