Açısal ve geri dönme


160

AngularJS'de ng-model seçeneklerini kullanarak bir modeli geri alabilirim.

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

Angular'da bir modeli nasıl geri alabilirim? Dokümanlarda zıplamayı aramaya çalıştım ama hiçbir şey bulamadım.

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

Bir çözüm, kendi geri dönme işlevimi yazmak olabilir, örneğin:

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

Ve benim html'm

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

Ama ben işlevde bir yapı arıyorum, Angular'da bir tane var mı?


3
Bu , görünüşe göre implante edilmemiş github.com/angular/angular/issues/1773 ile ilgili olabilir .
Eric Martinez

Angular 7 with RxJS v6 freakyjolly.com/…
Code Spy için

Yanıtlar:


202

RC.5 için güncellendi

Angular 2 debounceTime()ile bir form kontrolünün valueChangesgözlemlenebilir olan RxJS operatörünü kullanarak geri dönebiliriz :

import {Component}   from '@angular/core';
import {FormControl} from '@angular/forms';
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" [formControl]="firstNameControl">
    <br>{{firstName}}`
})
export class AppComponent {
  firstName        = 'Name';
  firstNameControl = new FormControl();
  formCtrlSub: Subscription;
  resizeSub:   Subscription;
  ngOnInit() {
    // debounce keystroke events
    this.formCtrlSub = this.firstNameControl.valueChanges
      .debounceTime(1000)
      .subscribe(newValue => this.firstName = newValue);
    // throttle resize events
    this.resizeSub = Observable.fromEvent(window, 'resize')
      .throttleTime(200)
      .subscribe(e => {
        console.log('resize event', e);
        this.firstName += '*';  // change something to show it worked
      });
  }
  ngDoCheck() { console.log('change detection'); }
  ngOnDestroy() {
    this.formCtrlSub.unsubscribe();
    this.resizeSub  .unsubscribe();
  }
} 

Plunker

Yukarıdaki kod ayrıca, aşağıdaki yorumda @albanx tarafından sorulduğu gibi pencere yeniden boyutlandırma olaylarının nasıl kısaltılacağına dair bir örnek de içerir.


Yukarıdaki kod muhtemelen bunu yapmanın Açısal yolu olsa da, verimli değildir. Her tuş vuruşu ve her yeniden boyutlandırma olayı, kaldırılsa ve kısaltılsa bile, değişiklik algılama çalışmasına neden olur. Başka bir deyişle, debouncing ve throttling , değişiklik algılamanın ne sıklıkta çalıştığını etkilemez . ( Tobias Bosch tarafından bunu onaylayan bir GitHub yorumu buldum .) Daldırıcıyı çalıştırdığınızda bunu görebilirsiniz ngDoCheck()ve giriş kutusuna yazdığınızda veya pencereyi yeniden boyutlandırdığınızda kaç kez çağrıldığını görebilirsiniz . (Yeniden boyutlandırma olaylarını görmek için pistonu ayrı bir pencerede çalıştırmak için mavi "x" düğmesini kullanın.)

Daha etkili bir teknik, RxJS Gözlemlenebilirliklerini Angular'ın "bölgesi" dışında, olaylardan yaratmaktır. Bu şekilde, bir olay her tetiklendiğinde değişiklik algılaması çağrılmaz. Ardından, abone geri arama yöntemlerinizde değişiklik algılamayı manuel olarak tetikleyin - yani, değişiklik algılamanın ne zaman çağrıldığını siz kontrol edersiniz:

import {Component, NgZone, ChangeDetectorRef, ApplicationRef, 
        ViewChild, ElementRef} from '@angular/core';
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 #input type=text [value]="firstName">
    <br>{{firstName}}`
})
export class AppComponent {
  firstName = 'Name';
  keyupSub:  Subscription;
  resizeSub: Subscription;
  @ViewChild('input') inputElRef: ElementRef;
  constructor(private ngzone: NgZone, private cdref: ChangeDetectorRef,
    private appref: ApplicationRef) {}
  ngAfterViewInit() {
    this.ngzone.runOutsideAngular( () => {
      this.keyupSub = Observable.fromEvent(this.inputElRef.nativeElement, 'keyup')
        .debounceTime(1000)
        .subscribe(keyboardEvent => {
          this.firstName = keyboardEvent.target.value;
          this.cdref.detectChanges();
        });
      this.resizeSub = Observable.fromEvent(window, 'resize')
        .throttleTime(200)
        .subscribe(e => {
          console.log('resize event', e);
          this.firstName += '*';  // change something to show it worked
          this.cdref.detectChanges();
        });
    });
  }
  ngDoCheck() { console.log('cd'); }
  ngOnDestroy() {
    this.keyupSub .unsubscribe();
    this.resizeSub.unsubscribe();
  }
} 

Plunker

Kullandığım ngAfterViewInit()yerine ngOnInit()sağlamak için inputElReftanımlanır.

detectChanges()bu bileşen ve alt bileşenleri üzerinde değişiklik algılaması yapacaktır. Kök bileĢeninden değiĢiklik algılamasını çalıĢtırmayı tercih ediyorsanız (yani, tam değiĢiklik algılaması denetimi yapın), ApplicationRef.tick()bunun yerine kullanın. ( ApplicationRef.tick()Pistondaki yorumlara bir çağrı koydum.) Çağrı yapılmasının tick()neden olacağını unutmayın ngDoCheck().


2
@Mark Rajcok Sanırım [değer] yerine [ngModel] kullanmalısınız, çünkü [değer] giriş değerini güncellemez.
Milad

1
herhangi bir genel debounce yöntemi var mı (örneğin pencere yeniden boyutlandırma olayına uygulamak için)?
albanx

1
@MarkRajcok Yanıtınızda tanımladığınız CD sorununun github.com/angular/zone.js/pull/843
Jefftopia

2
Bellek sızıntılarını önlemek için ne zaman abonelikten çıkmamız gerekir?
slanden

1
Evet @slanden e acccording netbasal.com/when-to-unsubscribe-in-angular-d61c6b21bad3 , biz çıkmak gerekir .fromEvent()abonelikler
Jon Onstott

153

Eğer uğraşmak istemiyorsanız @angular/forms, sadece Subjectdeğişiklik bağlamaları olan bir RxJS kullanabilirsiniz .

view.component.html

<input [ngModel]='model' (ngModelChange)='changed($event)' />

view.component.ts

import { Subject } from 'rxjs/Subject';
import { Component }   from '@angular/core';
import 'rxjs/add/operator/debounceTime';

export class ViewComponent {
    model: string;
    modelChanged: Subject<string> = new Subject<string>();

    constructor() {
        this.modelChanged
            .debounceTime(300) // wait 300ms after the last event before emitting last event
            .distinctUntilChanged() // only emit if value is different from previous value
            .subscribe(model => this.model = model);
    }

    changed(text: string) {
        this.modelChanged.next(text);
    }
}

Bu değişiklik algılamayı tetikler. Değişiklik algılamayı tetiklemeyen bir yol için Mark'ın cevabına göz atın.


Güncelleme

.pipe(debounceTime(300), distinctUntilChanged()) rxjs 6 için gereklidir.

Misal:

   constructor() {
        this.modelChanged.pipe(
            debounceTime(300), 
            distinctUntilChanged())
            .subscribe(model => this.model = model);
    }

5
Bu çözümü tercih ederim! Açısal 2.0.0, rxjs 5.0.0-beta 12
alsco77

2
Mükemmel çalıştı, basit ve net, hiçbir form dahil. Açısal 4.1.3'deyim, rxjs 5.1.1
beşinci

Gerektiğinde formlarla çalışma seçeneğine sahip olduğu için bu üstün bir çözüm olduğunu düşünüyorum, ancak bu bağımlılığı uygulamayı daha basit hale getiriyor. Teşekkürler.
Max

2
.pipe(debounceTime(300), distinctUntilChanged())6
Icycool

Çözüm beni kurtardı. Sütun sayısı değiştiğinde çalışmayı durduran bir keyUpolayı kullanıyorduminput.nativeElementmat-table
igorepst

35

Direktif olarak uygulanabilir

import { Directive, Input, Output, EventEmitter, OnInit, OnDestroy } from '@angular/core';
import { NgControl } from '@angular/forms';
import 'rxjs/add/operator/debounceTime';
import 'rxjs/add/operator/distinctUntilChanged';
import { Subscription } from 'rxjs';

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

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

  private isFirstChange: boolean = true;
  private subscription: Subscription;

  constructor(public model: NgControl) {
  }

  ngOnInit() {
    this.subscription =
      this.model.valueChanges
        .debounceTime(this.debounceTime)
        .distinctUntilChanged()
        .subscribe(modelValue => {
          if (this.isFirstChange) {
            this.isFirstChange = false;
          } else {
            this.onDebounce.emit(modelValue);
          }
        });
  }

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

}

gibi kullan

<input [(ngModel)]="value" (onDebounce)="doSomethingWhenModelIsChanged($event)">

bileşen örneği

import { Component } from "@angular/core";

@Component({
  selector: 'app-sample',
  template: `
<input[(ngModel)]="value" (onDebounce)="doSomethingWhenModelIsChanged($event)">
<input[(ngModel)]="value" (onDebounce)="asyncDoSomethingWhenModelIsChanged($event)">
`
})
export class SampleComponent {
  value: string;

  doSomethingWhenModelIsChanged(value: string): void {
    console.log({ value });
  }

  async asyncDoSomethingWhenModelIsChanged(value: string): Promise<void> {
    return new Promise<void>(resolve => {
      setTimeout(() => {
        console.log('async', { value });
        resolve();
      }, 1000);
    });
  }
} 

1
benim için çalışan daha fazla ithalatla: import "rxjs / add / operator / debounceTime"; import "rxjs / add / operator / differenttUntilChanged";
Sbl

2
Bu şimdiye kadar uygulamayı geniş uygulamayı en basit hale getiriyor
joshcomley

1
isFirstChange başlatma sırasında yaymamak için kullanılır
Oleg Polezky

2
Açısal 8 ve rxjs 6.5.2'de aşağıdaki değişikliklerle çalışır. Eğer boru sözdizimi kullanmak istiyorsanız, aşağıdakileri değiştirin: import 'rxjs/add/operator/debounceTime'; import 'rxjs/add/operator/distinctUntilChanged';için import { debounceTime, distinctUntilChanged } from 'rxjs/operators';ve this.model.valueChanges .debounceTime(this.debounceTime) .distinctUntilChanged()içinthis.model.valueChanges .pipe( debounceTime(this.debounceTime), distinctUntilChanged() )
kumaheiyama

1
Açısal 9 ve rxjs 6.5.4 @ kumaheiyama yaptığı açıklamada değişikliklerle yaptığı açıklamada çalışıyor. Yönergeyi oluşturduğunuz modüle aktarmayı unutmayın. Bu yönergeyi oluşturduğunuz modülü, kullandığınız modüle eklemeyi de unutmayın.
Filip Savic

29

Konu eski olduğu için, cevapların çoğu işi yok üzerinde açısal 6/7/8/9 ve / veya diğer kütüphanelerini kullanırlar.
İşte RxJS ile Angular 6+ için kısa ve basit bir çözüm.

Önce gerekli şeyleri içe aktarın:

import { Component, OnInit, OnDestroy } from '@angular/core';
import { Subject, Subscription } from 'rxjs';
import { debounceTime, distinctUntilChanged } from 'rxjs/operators';

Başlangıç ​​tarihi ngOnInit:

export class MyComponent implements OnInit, OnDestroy {
  public notesText: string;
  private notesModelChanged: Subject<string> = new Subject<string>();
  private notesModelChangeSubscription: Subscription

  constructor() { }

  ngOnInit() {
    this.notesModelChangeSubscription = this.notesModelChanged
      .pipe(
        debounceTime(2000),
        distinctUntilChanged()
      )
      .subscribe(newText => {
        this.notesText = newText;
        console.log(newText);
      });
  }

  ngOnDestroy() {
    this.notesModelChangeSubscription.unsubscribe();
  }
}

Şu şekilde kullanın:

<input [ngModel]='notesText' (ngModelChange)='notesModelChanged.next($event)' />

Not: Daha karmaşık ve verimli çözümler için yine de diğer yanıtları kontrol etmek isteyebilirsiniz.


1
Neden yok etme işleminden çıkmıyorsunuz?
Virendra Singh Rathore

Güncellenmiş. Fark ettiğiniz için teşekkürler!
Sadece

1
@JustShadow Teşekkürler! Gerçekten yardımcı oldu.
Niral Munjariya

Bu ilk denemede mükemmel çalışıyor. Ancak aranan metni bir şekilde sildiğimde, bir sonraki isteğin yanıtlanması çok uzun sürüyor.
Sadiksha Gautam

Bu garip. Hala benim tarafımda çalışıyor. Lütfen daha fazla bilgi paylaşabilir misiniz, belki yeni bir soru açabilir misiniz?
Sadece Gölge

28

Açısal1'deki gibi doğrudan erişilemez, ancak NgFormControl ve RxJS gözlemlenebilirleriyle kolayca oynayabilirsiniz:

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

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

Bu blog gönderisi bunu açıkça açıklıyor: http://blog.thoughtram.io/angular/2016/01/06/taking-advantage-of-observables-in-angular2.html

Burada bir otomatik tamamlama içindir, ancak tüm senaryoları çalıştırır.


ancak hizmetten bir hata var, bu tekrar çalışmıyor
Arun Tyagi

Örneği anlamıyorum. [...] tek yönlü hedef bağlamasıdır. Konteyner neden bildirilebilir valueChanges? sth olması gerekmiyor. gibi (ngFormControl)="..."mi?
phil294

20

Sen olabilir oluşturmak bir RxJS (v.6) gözlemlenebilir ne gibi yapar.

view.component.html

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

view.component.ts

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

export class ViewComponent {
    searchChangeObserver;

  onSearchChange(searchValue: string) {

    if (!this.searchChangeObserver) {
      Observable.create(observer => {
        this.searchChangeObserver = observer;
      }).pipe(debounceTime(300)) // wait 300ms after the last event before emitting last event
        .pipe(distinctUntilChanged()) // only emit if value is different from previous value
        .subscribe(console.log);
    }

    this.searchChangeObserver.next(searchValue);
  }  


}

Teşekkür ederim, ancak ithalatın olması gerektiğini düşünüyorum, ithalat rsjs/Rxyazarken kullandığınızda hatalar vardı ... yani benim durumumda şimdi:import { Observable } from 'rxjs/Rx';
ghiscoding

2
@ghiscoding Bu rxjs sürümüne bağlıdır. Sürümünde 6'da öyle: import { Observable } from 'rxjs';.
Matthias

Teşekkürler! Bir yana, sadece bir pipeçağrı kullanabilirsinizpipe(debounceTime(300), distinctUntilChanged())
al.

1
searchChangeObserver bir Abone, dolayısıyla searchChangeSubscriber daha iyi bir isim olacak.
Khonsort

12

Lodash kullanan herkes için, son derece kolaydır sektirilmesini hiçbir işlevi:

changed = _.debounce(function() {
    console.log("name changed!");
}, 400);

şablonunuza böyle bir şey atmanız yeterlidir:

<(input)="changed($event.target.value)" />

3
veya sadece (input) = "değişti ($ event.target.value)"
Jamie Kudla

1
:) lodash ile cevap verdiğiniz için teşekkür ederiz
Vamsi

Bunun, her bir değişiklikte, geri dönme işleminden bağımsız olarak Açısal değişiklik algılamasını tetikleyeceğine inanıyorum.
AsGoodAsItGets

5

Doğrudan başlatma fonksiyonunda başlatma abonesi ile çözüm:

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

Ve html:

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

Açısal 8 ana otomatik tamamlama metin kutusu için tamamen iyi çalışır. Çok teşekkürler.
Jasmin Akther Suma

4

Bunu bir debounce dekoratör yazarak çözdüm. Açıklanan sorun, @debounceAccessor özelliği mülkün ayarlanan erişimcisine uygulanarak çözülebilir.

Ayrıca, diğer durumlar için yararlı olabilecek yöntemler için ek bir debounce dekoratör sağladım.

Bu, bir özelliği veya yöntemi kaldırmayı çok kolaylaştırır. Parametre, aşağıdaki örnekte 100 ms açılma süresinin geçmesi gereken milisaniye sayısıdır.

@debounceAccessor(100)
set myProperty(value) {
  this._myProperty = value;
}


@debounceMethod(100)
myMethod (a, b, c) {
  let d = a + b + c;
  return d;
}

İşte dekoratörler için kod:

function debounceMethod(ms: number, applyAfterDebounceDelay = false) {

  let timeoutId;

  return function (target: Object, propName: string, descriptor: TypedPropertyDescriptor<any>) {
    let originalMethod = descriptor.value;
    descriptor.value = function (...args: any[]) {
      if (timeoutId) return;
      timeoutId = window.setTimeout(() => {
        if (applyAfterDebounceDelay) {
          originalMethod.apply(this, args);
        }
        timeoutId = null;
      }, ms);

      if (!applyAfterDebounceDelay) {
        return originalMethod.apply(this, args);
      }
    }
  }
}

function debounceAccessor (ms: number) {

  let timeoutId;

  return function (target: Object, propName: string, descriptor: TypedPropertyDescriptor<any>) {
    let originalSetter = descriptor.set;
    descriptor.set = function (...args: any[]) {
      if (timeoutId) return;
      timeoutId = window.setTimeout(() => {
        timeoutId = null;
      }, ms);
      return originalSetter.apply(this, args);
    }
  }
}

Yöntem dekoratörü için, geri dönme gecikmesinden SONRA yöntemi tetiklemenize izin veren ek bir parametre ekledim. Bunu, örneğin fareyle üzerine gelme veya yeniden boyutlandırma olaylarıyla birleştiğinde kullanabileceğim şekilde yaptım, burada yakalamanın olay akışının sonunda olmasını istedim. Ancak bu durumda, yöntem bir değer döndürmez.


3

NgModel'in varsayılan viewToModelUpdate işlevini boş bir işlevle değiştiren bir [debounce] yönergesi oluşturabiliriz.

Yönerge Kodu

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

Bu nasıl kullanılır

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

2

HTML dosyası:

<input [ngModel]="filterValue"
       (ngModelChange)="filterValue = $event ; search($event)"
        placeholder="Search..."/>

TS dosyası:

timer = null;
time = 250;
  search(searchStr : string) : void {
    clearTimeout(this.timer);
    this.timer = setTimeout(()=>{
      console.log(searchStr);
    }, time)
  }

2

Herhangi bir kontrole uygulayabileceğiniz bir direktif oluşturmak basit bir çözüm olacaktır.

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

kullanımı olurdu

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

Bu sınıf derlemekten çok uzak Angular 7.
Stephane

1

Bu konuda saatler geçirdim, umarım başka birini zamandan kurtarabilirim. Bana göre, debouncebir kontrol üzerinde kullanmak için aşağıdaki yaklaşım benim için daha sezgisel ve daha kolay anlaşılır. Otomatik tamamlama için angular.io docs çözümüne dayanıyor, ancak verileri DOM'a bağlı kalmaya gerek kalmadan aramaları durdurma yeteneğim var.

Plunker

Bunun için bir kullanım senaryosu, bir kullanıcının daha önce alıp almadığını görmek için yazıldıktan sonra bir kullanıcı adını kontrol ediyor ve kullanıcıyı uyarıyor olabilir.

Not: unutmayın, (blur)="function(something.value)ihtiyaçlarınıza bağlı olarak sizin için daha anlamlı olabilir.


1

RxJS v6 ile Açısal 7'de DebounceTime

Kaynak Bağlantı

Demo Bağlantısı

resim açıklamasını buraya girin

HTML Şablonunda

<input type="text" #movieSearchInput class="form-control"
            placeholder="Type any movie name" [(ngModel)]="searchTermModel" />

Bileşende

    ....
    ....
    export class AppComponent implements OnInit {

    @ViewChild('movieSearchInput') movieSearchInput: ElementRef;
    apiResponse:any;
    isSearching:boolean;

        constructor(
        private httpClient: HttpClient
        ) {
        this.isSearching = false;
        this.apiResponse = [];
        }

    ngOnInit() {
        fromEvent(this.movieSearchInput.nativeElement, 'keyup').pipe(
        // get value
        map((event: any) => {
            return event.target.value;
        })
        // if character length greater then 2
        ,filter(res => res.length > 2)
        // Time in milliseconds between key events
        ,debounceTime(1000)        
        // If previous query is diffent from current   
        ,distinctUntilChanged()
        // subscription for response
        ).subscribe((text: string) => {
            this.isSearching = true;
            this.searchGetCall(text).subscribe((res)=>{
            console.log('res',res);
            this.isSearching = false;
            this.apiResponse = res;
            },(err)=>{
            this.isSearching = false;
            console.log('error',err);
            });
        });
    }

    searchGetCall(term: string) {
        if (term === '') {
        return of([]);
        }
        return this.httpClient.get('http://www.omdbapi.com/?s=' + term + '&apikey=' + APIKEY,{params: PARAMS.set('search', term)});
    }

    }

1

Bunu bir dekoratör kullanarak da çözebilirsiniz, Örneğin, utils-decorator lib ( npm install utils-decorators) ' den debounce dekoratör kullanarak :

import {debounce} from 'utils-decorators';

class MyAppComponent {

  @debounce(500)
  firstNameChanged($event, first) {
   ...
  }
}

0

Bu şimdiye kadar bulduğum en iyi çözüm. Günceller ngModelüzerinde blurvedebounce

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 adresinden ödünç alındığı gibi

Sonra HTML'de:

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

Açık blurmodelin açıkça düz javascript kullanarak güncellenir.

Burada örnek: https://stackblitz.com/edit/ng2-debounce-working

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.