javascriptangular

Angular 2: Debounce (ngModelChange)?


Is there a way to debounce the template directive (ngModelChange)?

Or, alternatively, what is the least-painful way to do it a different way?

The closest answer I see is this: How to watch for form changes in Angular 2?

So, for example, I have a text input, I want to get onChange updates, but I want to debounce it down from every keystroke:

<input type="text" class="form-control" placeholder="Enter a value" name="foo" [(ngModel)]="input.event.value" (ngModelChange)="onFieldChange($event, input)">

Debounce onFieldChange()


Solution

  • EDIT

    In new version of Angular you can use updateOn in ngModelOption to set 'blur' for example. Link to angular.io documentation.

    Code example :

    <input [(ngModel)]="value"
      [ngModelOptions]="{ updateOn: 'blur' }"
      (ngModelChange)="updateOnlyOnBlur($event)"> 
    

    LEGACY

    Here's the less painful way of debouncing keystrokes if you don't want to use the formcontrol approach.

    search.component.html

    <input type="text" placeholder="Enter a value" name="foo" [(ngModel)]="txtQuery" (ngModelChange)="onFieldChange($event)">
    

    search.component.ts

        export class SearchComponent {
        
             txtQuery: string; // bind this to input with ngModel
             txtQueryChanged: Subject<string> = new Subject<string>();
        
             constructor() {
              this.txtQueryChanged
                .debounceTime(1000) // wait 1 sec after the last event before emitting last event
                .distinctUntilChanged() // only emit if value is different from previous value
                .subscribe(model => {
                  this.txtQuery = model;
        
                  // Call your function which calls API or do anything you would like do after a lag of 1 sec
                  this.getDataFromAPI(this.txtQuery);
                 });
            }
        
        onFieldChange(query:string){
          this.txtQueryChanged.next(query);
        }
    }