在AngularJS中,我可以使用ng-model选项来撤销一个模型。

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

如何在Angular中释放一个模型? 我试着在文档里搜索debounce,但什么都没找到。

https://angular.io/search/#stq=debounce&stp=1

一个解决方案是编写我自己的debounce函数,例如:

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);

我的html

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

但我正在寻找一个内置函数,Angular中有吗?


当前回答

不像在angar1中那样直接访问,但你可以轻松地使用NgFormControl和RxJS的观察对象:

<input type="text" [ngFormControl]="term"/>

this.items = this.term.valueChanges
  .debounceTime(400)
  .distinctUntilChanged()
  .switchMap(term => this.wikipediaService.search(term));

这篇博文解释得很清楚: http://blog.thoughtram.io/angular/2016/01/06/taking-advantage-of-observables-in-angular2.html

这里是自动补全,但它适用于所有场景。

其他回答

不像在angar1中那样直接访问,但你可以轻松地使用NgFormControl和RxJS的观察对象:

<input type="text" [ngFormControl]="term"/>

this.items = this.term.valueChanges
  .debounceTime(400)
  .distinctUntilChanged()
  .switchMap(term => this.wikipediaService.search(term));

这篇博文解释得很清楚: http://blog.thoughtram.io/angular/2016/01/06/taking-advantage-of-observables-in-angular2.html

这里是自动补全,但它适用于所有场景。

这是我迄今为止找到的最好的解决办法。更新ngModelon的模糊和反弹

import { Directive, Input, Output, EventEmitter,ElementRef } from '@angular/core';
import { NgControl, NgModel } from '@angular/forms';
import 'rxjs/add/operator/debounceTime'; 
import 'rxjs/add/operator/distinctUntilChanged';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/observable/fromEvent';
import 'rxjs/add/operator/map';

@Directive({
    selector: '[ngModel][debounce]',
})
export class DebounceDirective {
    @Output()
    public onDebounce = new EventEmitter<any>();

    @Input('debounce')
    public debounceTime: number = 500;

    private isFirstChange: boolean = true;

    constructor(private elementRef: ElementRef, private model: NgModel) {
    }

    ngOnInit() {
        const eventStream = Observable.fromEvent(this.elementRef.nativeElement, 'keyup')
            .map(() => {
                return this.model.value;
            })
            .debounceTime(this.debounceTime);

        this.model.viewToModelUpdate = () => {};

        eventStream.subscribe(input => {
            this.model.viewModel = input;
            this.model.update.emit(input);
        });
    }
}

引自https://stackoverflow.com/a/47823960/3955513

然后在HTML中:

<input [(ngModel)]="hero.name" 
        [debounce]="3000" 
        (blur)="hero.name = $event.target.value"
        (ngModelChange)="onChange()"
        placeholder="name">

在模糊模型是显式更新使用纯javascript。

例如:https://stackblitz.com/edit/ng2-debounce-working

简单的解决方法是创建一个可以应用于任何控件的指令。

import { Directive, ElementRef, Input, Renderer, HostListener, Output, EventEmitter } from '@angular/core';
import { NgControl } from '@angular/forms';

@Directive({
    selector: '[ngModel][debounce]',
})
export class Debounce 
{
    @Output() public onDebounce = new EventEmitter<any>();

    @Input('debounce') public debounceTime: number = 500;

    private modelValue = null;

    constructor(public model: NgControl, el: ElementRef, renderer: Renderer){
    }

    ngOnInit(){
        this.modelValue = this.model.value;

        if (!this.modelValue){
            var firstChangeSubs = this.model.valueChanges.subscribe(v =>{
                this.modelValue = v;
                firstChangeSubs.unsubscribe()
            });
        }

        this.model.valueChanges
            .debounceTime(this.debounceTime)
            .distinctUntilChanged()
            .subscribe(mv => {
                if (this.modelValue != mv){
                    this.modelValue = mv;
                    this.onDebounce.emit(mv);
                }
            });
    }
}

用法是

<textarea [ngModel]="somevalue"   
          [debounce]="2000"
          (onDebounce)="somevalue = $event"                               
          rows="3">
</textarea>

我们可以创建一个[debounce]指令,用一个空函数覆盖ngModel的默认viewToModelUpdate函数。

指令代码

@Directive({ selector: '[debounce]' })
export class MyDebounce implements OnInit {
    @Input() delay: number = 300;

    constructor(private elementRef: ElementRef, private model: NgModel) {
    }

    ngOnInit(): void {
        const eventStream = Observable.fromEvent(this.elementRef.nativeElement, 'keyup')
            .map(() => {
                return this.model.value;
            })
            .debounceTime(this.delay);

        this.model.viewToModelUpdate = () => {};

        eventStream.subscribe(input => {
            this.model.viewModel = input;
            this.model.update.emit(input);
        });
    }
}

如何使用

<div class="ui input">
  <input debounce [delay]=500 [(ngModel)]="myData" type="text">
</div>

在事件函数中直接初始化订阅者的解决方案:

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

class MyAppComponent {
    searchTermChanged: Subject<string> = new Subject<string>();

    constructor() {
    }

    onFind(event: any) {
        if (this.searchTermChanged.observers.length === 0) {
            this.searchTermChanged.pipe(debounceTime(1000), distinctUntilChanged())
                .subscribe(term => {
                    // your code here
                    console.log(term);
                });
        }
        this.searchTermChanged.next(event);
    }
}

和html:

<input type="text" (input)="onFind($event.target.value)">