2

I have an input search element that I detect keyup and I want to use debounce to limit request made to the API but I can't get it working. I'm just trying to test debounceTime and distinctUntilChanged.

I have already tried (Keyup) but can't get it working.

<input (keyup)="onKeyUp($event)"  id="testInput" autocomplete="off" type="text" name="searchFilterText" class="m-list-search__form-input" value="" placeholder="Search...">

Here is the code from the typescript file.

searchInput = document.getElementById('testInput');
observable: any;

/// <summary>
/// Process the search term provided on key up for the input field.
/// </summary>
/// <param name="searchTerm">The search term.</param>
onKeyUp(event: KeyboardEvent) {
    //console.log(event);
    let element = event.target as HTMLInputElement;
    let value = element.value;

    this.observable = fromEvent(this.searchInput, event.type)
        .debounceTime(500) // millisecs until value gets emitted.
        .distinctUntilChanged()
        .subscribe(function (event) {
            console.log(event.target.value);
        });
}

The expected result is a delayed search result value in the console log using debounceTime and distinctUntilChanged.

0

1 Answer 1

9

You could try this:

Template

<input  
       id="testInput" autocomplete="off"
       type="text" #searchText
       name="searchFilterText" class="m-list-search__form-input"
       value=""
       placeholder="Search...">

Notice the template reference variable: #searchText. This allows access to the input element without needing getElementById (which is not normally recommended to use in an Angular app).

Component

import { Component, AfterViewInit, ViewChild } from '@angular/core';
import { fromEvent } from 'rxjs';
import { debounceTime } from 'rxjs/operators';

@Component({
   templateUrl: './search.component.html'
})
export class SearchComponent implements AfterViewInit {
  @ViewChild('searchText') searchTextRef;

  ngAfterViewInit() {
    if (this.searchTextRef) {
      fromEvent(this.searchTextRef.nativeElement, 'keyup')
        .pipe(
            debounceTime(500),
            distinctUntilChanged()
        ).subscribe(
          value => console.log(this.searchTextRef.nativeElement.value)
        )
    }
  }
}

This code uses @ViewChild to get the reference to the element marked with the #searchText template reference variable.

It then uses code similar to what you had for the debounceTime.

I have a stackblitz here: https://stackblitz.com/edit/angular-debounce-deborahk

And you can find more info here: Observable.fromEvent - RXJS

Note: This is even easier if you use reactive forms as you can directly access the valueChanges observable for any input element on a form.

Reactive Forms

Template

<input  
       id="testInput"
       [formControl]="search"
       autocomplete="off"
       type="text"
       class="m-list-search__form-input"
       value=""
       placeholder="Search...">

Notice the formControl directive.

Component

  // For reactive forms
  search = new FormControl();

  ngOnInit() {
    this.search.valueChanges
            .pipe(
          debounceTime(500),
          distinctUntilChanged()
        ).subscribe(
          value => console.log("Reactive Forms implementation: " + value)
        )
  }
Sign up to request clarification or add additional context in comments.

6 Comments

this is great thanks. Do you have any ideas of how to include distinctUntilChanged() into the logic?
What would you expect distinctUntilChanged to do in this context?
If I type the word test then type test1 and then type test the last value change gets ignored right or have I got it wrong and it's not needed in my case.
Just add it within the pipe. i'll update my answer.
Hi, @DeborahK does order of distinctUntilChanged, debounceTime matter? i have noticed making distinctUntilChanged before debounceTime make network call each time even if value is same. Help would be appreciated.
|

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.