koningdavid koningdavid - 3 months ago 541
Javascript Question

Angular2 and debounce

In AngularJS I can debounce a model by using ng-model options.

ng-model-options="{ debounce: 1000 }"


How can I debounce a model in Angular2? I tried to search for debounce in the docs but I couldn't find anything.

https://angular.io/docs/js/latest/api/test/#stq=debounce&stp=1

A solution would be to write my own debounce function, for example:

import {Component, Template, bootstrap} from 'angular2/angular2';

// Annotation section
@Component({
selector: 'my-app'
})
@Template({
url: 'app.html'
})
// Component controller
class MyAppComponent {
constructor() {
this.firstName = 'Name';
}

changed($event, el){
console.log("changes", this.name, el.value);
this.name = el.value;
}

firstNameChanged($event, first){
if (this.timeoutId) window.clearTimeout(this.timeoutID);
this.timeoutID = window.setTimeout(() => {
this.firstName = first.value;
}, 250)
}

}
bootstrap(MyAppComponent);


And my html

<input type=text [value]="firstName" #first (keyup)="firstNameChanged($event, first)">


But I'm looking for a build in function, is there one in Angular2?

Answer

@bertrandg's answer is good (+1), but we don't need distinctUntilChanged() or switchMap() here. And since I didn't like having to go read a blog post to figure out how to get a working example, here's a working example so others don't have to do the same:

import {Component} from '@angular/core';
import {Control} from '@angular/common'; 
import {Observable} from 'rxjs/Observable';
import 'rxjs/add/operator/debounceTime';
import 'rxjs/add/operator/throttleTime';
import 'rxjs/add/observable/fromEvent';

@Component({
  selector: 'my-app',
  template: `<input type=text [value]="firstName" [ngFormControl]="firstNameControl">
    <br>{{firstName}}`
})
export class AppComponent {
  firstName = 'Name';
  constructor() { 
    this.firstNameControl = new Control();
  }
  ngOnInit() {
    this.firstNameControl.valueChanges
      .debounceTime(1000)
      .subscribe(newValue => this.firstName = newValue);

    Observable.fromEvent(window, 'resize')
      .throttleTime(1000)
      .subscribe(e => {
        console.log('resize event', e);
        this.firstName += '*';
      });
  }
} 

Plunker

The code also includes an example of how to throttle window resize events, as asked by @albanx in a comment below. Note that Angular change detection will now run for each resize event, even if the event is throttled. To avoid that, see the technique presented in this answer.