Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to implement a debounce time in keyup event in Angular 6

People also ask

What is debounce time in angular?

DebounceTime & Debounce are the Angular RxJs Operators. Both emit values from the source observable, only after a certain amount of time has elapsed since the last value. Both emit only the latest value and discard any intermediate values.

How do I use debounceTime in angular 6?

Angular 6 onwards, debounceTime is imported as following. import { debounceTime } from 'rxjs/operators'; It is used with pipe operator of Observable . debounceTime is useful in operation where user changes inputs frequently such as search operation.

What is Debouncing in angular?

Debouncing is the delay of a function/method execution or an action for a period of the specified time. During this specified time, calls to the method/function or action are collected and executes each one when the specified has elapsed.

How do you use debounce RxJS?

RxJS debounce() Filtering Operator RxJS debounce() operator is a filtering operator that emits a value from the source Observable only after a while (exactly after a particular period). The emission is determined by another input given as Observable or promise.


In the component you can do somthing like this. Create RxJS Subject, In search method which is called on keyup event, do .next() on this Subject you have created. Then subscribe in ngOnInit() will debounce for 1 second, as in below code.

searchTextChanged = new Subject<string>();
constructor(private http:Http) {

}


ngOnInit(): void {
    this.subscription = this.searchTextChanged
        .debounceTime(1000)
        .distinctUntilChanged()
        .mergeMap(search => this.getValues())
        .subscribe(() => { });
}

getValues() {
    return this.http.get("https://www.example.com/search/?q="+this.q)
    .map(
      (res:Response) => {
          const studentResult = res.json();
          console.log(studentResult);
          if(studentResult.success) {
            this.results = studentResult.data;
          } else {
            this.results = [];
          }
      }
    )
}

search($event) {
    this.searchTextChanged.next($event.target.value);
}

rxjs v6 has several breaking changes including simplifying import points for operators. Try installing rxjs-compat, which adds back those import paths until the code has been migrated.

Import the necessary operators from RxJS. Below ones are for RxJS 5.x

import { Subject } from "rxjs/Subject";
import "rxjs/add/operator/debounceTime";
import "rxjs/add/operator/distinctUntilChanged";
import { Observable } from "rxjs/Observable";
import "rxjs/add/operator/mergeMap";

For anyone coming across this in a newer version of angular (and rxjs).

The new Rxjs has pipeable operators and they can be used like this (from the accepted answers code)

ngOnInit() {
 this.subscription = this.searchTextChanged.pipe(
   debounceTime(1000),
   distinctUntilChanged(),
   mergeMap(search => this.getValues())
  ).subscribe((res) => {
    console.log(res);
  });

Also, you can use angular formControls to bind the input search field

<input  class="form-control form-control-lg" 
type="text" [formControl]="searchField"
placeholder="Search student by id or firstname or lastname">

and use valueChanges observable on our searchField to react to changes of out search field in your App.component.ts file.

searchField: FormControl; 

ngOnInit() {
    this.searchField.valueChanges
      .debounceTime(5000) 
      .subscribe(term => {
    // call your service endpoint.
      });
}

optionally you can use distinctUntilChanged ( which only publishes to its output stream if the value being published is different from the previous one)

searchField: FormControl; 

ngOnInit() {
    this.searchField.valueChanges
      .debounceTime(5000) 
     .distinctUntilChanged()
     .subscribe(term => {
            // call your service endpoint.
      });
}

If you are using angular 6 and rxjs 6, try this:
Notice the .pipe(debounceTime(1000)) before your subscribe

import { debounceTime } from 'rxjs/operators';


search() {
    this.http.get("https://www.example.com/search/?q="+this.q)
    .pipe(debounceTime(1000))
    .subscribe(
      (res:Response) => {
          const studentResult = res.json();
          console.log(studentResult);
          if(studentResult.success) {
            this.results = studentResult.data;
          } else {
            this.results = [];
          }
      }
    )
  }

Just use like this, without RXJS.

It may call 'search()' function itself every keyups, but it does not call inside contents of the function(such as http connect) every time. Much simple solution.

export class MyComponent implements OnInit {

  debounce:any;

  constructor(){}
  
  search(){
    clearTimeout(this.debounce);
    this.debounce = setTimeout(function(){
      // Your Http Function..
    },500); // Debounce time is set to 0.5s
  }
}

user.component.html

   <input type="text" #userNameRef class="form-control"  name="userName" >  <!-- template-driven -->
 <form [formGroup]="regiForm"> 
      email: <input formControlName="emailId"> <!-- formControl -->
    </form>

user.component.ts

       import { fromEvent } from 'rxjs';
       import { switchMap,debounceTime, map } from 'rxjs/operators';


        @Component({
          selector: 'app-user',
          templateUrl: './user.component.html',
          styleUrls: ['./user.component.css']
        })
        export class UserComponent implements OnInit {

          constructor(private userService : UserService) { }


             @ViewChild('userNameRef') userNameRef : ElementRef;

             emailId = new FormControl(); 
   regiForm: FormGroup = this.formBuilder.group({
      emailId: this.bookId
   });   

             ngOnInit() {

                    fromEvent(this.userNameRef.nativeElement,"keyup").pipe(
                    debounceTime(3000),
                    map((userName : any) =>userName.target.value )
                  ).subscribe(res =>{
                    console.log("User Name is :"+ res);

                  } );
    //--------------For HTTP Call------------------

                  fromEvent(this.userNameRef.nativeElement,"keyup").pipe(
                    debounceTime(3000),
                    switchMap((userName : any) =>{
                   return this.userService.search(userName.target.value)
                 })
                  ).subscribe(res =>{
                    console.log("User Name is :"+ res);

                  } );



----------
                // For formControl 

                  this.emailId.valueChanges.pipe(
                  debounceTime(3000),
                  switchMap(emailid => {
                         console.log(emailid);
                        return this.userService.search(emailid);
                        })
                         ).subscribe(res => {
                               console.log(res);
                                    });


            }

*Note: make sure that your input element is not present in ngIf Block.