简体   繁体   English

Angular 2:去抖动(ngModelChange)?

[英]Angular 2: Debounce (ngModelChange)?

Is there a way to debounce the template directive (ngModelChange) ?有没有办法去抖动模板指令(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?我看到的最接近的答案是: 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:所以,例如,我有一个文本输入,我想获得 onChange 更新,但我想从每次击键中消除它:

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

Debounce onFieldChange()去抖动onFieldChange()

EDIT编辑

In new version of Angular you can use updateOn in ngModelOption to set 'blur' for example.例如,在 Angular 的新版本中,您可以使用ngModelOption updateOn来设置'blur' Link to angular.io documentation .链接到 angular.io 文档

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.如果您不想使用formcontrol方法,这里有一种不那么痛苦的击键formcontrol方法。

search.component.html search.component.html

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

search.component.ts 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);
    }
}

For RxJs 6+对于 RxJs 6+

The chosen answer won't work for RxJs 6+.所选答案不适用于 RxJs 6+。 Here is what you have to change:这是您必须更改的内容:

The imports have to look like this:进口必须是这样的:

import {Subject} from "rxjs";
import {debounceTime, distinctUntilChanged} from "rxjs/operators";

You need to call pipe :您需要调用pipe

// ...
this.txtQueryChanged
   .pipe(debounceTime(1000), distinctUntilChanged())
   .subscribe(model => {
       this.txtQuery = model;
       // api call
   });
 // ...

Take a look atthis article for further reading.请查看这篇文章以进一步阅读。

I've written a little directive to solve this.我写了一个小指令来解决这个问题。

How to use it:如何使用它:

<input [ngModel]="someValue" (ngModelChangeDebounced)="someValue = $event">

You can optionally set a debounce time (default is 500):您可以选择设置去抖动时间(默认为 500):

[ngModelChangeDebounceTime]="200"

The directive itself:指令本身:

@Directive({
  selector: '[ngModelChangeDebounced]',
})
export class NgModelChangeDebouncedDirective implements OnDestroy {
  @Output()
  ngModelChangeDebounced = new EventEmitter<any>();
  @Input()
  ngModelChangeDebounceTime = 500; // optional, 500 default

  subscription: Subscription;
  ngOnDestroy() {
    this.subscription.unsubscribe();
  }

  constructor(private ngModel: NgModel) {
    this.subscription = this.ngModel.control.valueChanges.pipe(
      skip(1), // skip initial value
      distinctUntilChanged(),
      debounceTime(this.ngModelChangeDebounceTime)
    ).subscribe((value) => this.ngModelChangeDebounced.emit(value));
  }
}

Stackblitz: https://stackblitz.com/edit/angular-9-0-0-rc-1-y2q2ss Stackblitz: https ://stackblitz.com/edit/angular-9-0-0-rc-1-y2q2ss

If you wanted to add debounceTime while doing http call you can use Subject which is very easy to use .如果您想在进行 http 调用时添加debounceTime ,您可以使用非常易于使用的Subject Which is also explained in angular2 tutorial - HTTP .这也在 angular2 教程 - HTTP 中进行了解释。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM