Di AngularJS saya dapat melakukan debo suatu model dengan menggunakan opsi ng-model.
ng-model-options="{ debounce: 1000 }"
Bagaimana saya bisa mendebo suatu model di Angular? Saya mencoba mencari debounce di dokumen tetapi saya tidak dapat menemukan apa pun.
https://angular.io/search/#stq=debounce&stp=1
Solusinya adalah menulis fungsi debounce saya sendiri, misalnya:
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);
Dan html saya
<input type=text [value]="firstName" #first (keyup)="firstNameChanged($event, first)">
Tapi saya mencari fungsi build, apakah ada di Angular?
javascript
angular
koningdavid
sumber
sumber
Jawaban:
Diperbarui untuk RC.5
Dengan Angular 2 kita dapat melakukan debounce menggunakan operator RxJS
debounceTime()
pada kontrol form yangvalueChanges
dapat diamati:Plunker
Kode di atas juga termasuk contoh bagaimana cara throttle window mengubah ukuran acara, seperti yang diminta oleh @albanx dalam komentar di bawah ini.
Meskipun kode di atas mungkin merupakan cara Angular untuk melakukannya, itu tidak efisien. Setiap keystroke dan setiap peristiwa pengubahan ukuran, meskipun mereka ditolak dan dicekik, menghasilkan perubahan pendeteksian berjalan. Dengan kata lain, debouncing dan pelambatan tidak mempengaruhi seberapa sering perubahan pendeteksian berjalan . (Saya menemukan komentar GitHub oleh Tobias Bosch yang mengkonfirmasi ini.) Anda dapat melihat ini ketika Anda menjalankan plunker dan Anda melihat berapa kali
ngDoCheck()
dipanggil ketika Anda mengetik ke dalam kotak input atau mengubah ukuran jendela. (Gunakan tombol "x" biru untuk menjalankan plunker di jendela terpisah untuk melihat ukurannya.)Teknik yang lebih efisien adalah membuat RxJS Dapat Diamati sendiri dari acara, di luar "zona" Angular. Dengan cara ini, deteksi perubahan tidak dipanggil setiap kali suatu peristiwa menyala. Kemudian, dalam metode panggilan balik berlangganan Anda, secara manual memicu deteksi perubahan - yaitu, Anda mengontrol kapan deteksi perubahan dipanggil:
Plunker
Saya menggunakan
ngAfterViewInit()
bukannyangOnInit()
untuk memastikan bahwainputElRef
itu didefinisikan.detectChanges()
akan menjalankan deteksi perubahan pada komponen ini dan anak-anaknya. Jika Anda lebih suka menjalankan deteksi perubahan dari komponen root (yaitu, jalankan pemeriksaan deteksi perubahan penuh) kemudian gunakanApplicationRef.tick()
. (Saya melakukan panggilan keApplicationRef.tick()
dalam komentar di plunker.) Perhatikan bahwa panggilantick()
akan menyebabkanngDoCheck()
dipanggil.sumber
.fromEvent()
langgananJika Anda tidak ingin berurusan
@angular/forms
, Anda bisa menggunakan RxJSSubject
dengan bindings perubahan.view.component.html
view.component.ts
Ini memicu deteksi perubahan. Untuk cara yang tidak memicu deteksi perubahan, periksa jawaban Mark.
Memperbarui
.pipe(debounceTime(300), distinctUntilChanged())
diperlukan untuk rxjs 6.Contoh:
sumber
.pipe(debounceTime(300), distinctUntilChanged())
diperlukan untuk rxjs 6keyUp
acara diinput.nativeElement
dalammat-table
, yang berhenti berfungsi ketika jumlah kolom diubahItu bisa diimplementasikan sebagai Petunjuk
gunakan seperti
sampel komponen
sumber
import 'rxjs/add/operator/debounceTime'; import 'rxjs/add/operator/distinctUntilChanged';
keimport { debounceTime, distinctUntilChanged } from 'rxjs/operators';
danthis.model.valueChanges .debounceTime(this.debounceTime) .distinctUntilChanged()
kethis.model.valueChanges .pipe( debounceTime(this.debounceTime), distinctUntilChanged() )
Karena topik sudah tua, sebagian besar jawaban tidak berfungsi pada Angular 6/7/8/9 dan / atau menggunakan lib lainnya.
Jadi di sini adalah solusi singkat dan sederhana untuk Angular 6+ dengan RxJS.
Impor barang-barang yang diperlukan terlebih dahulu:
Inisialisasi pada
ngOnInit
:Gunakan cara ini:
PS: Untuk solusi yang lebih kompleks dan efisien Anda mungkin masih ingin memeriksa jawaban lain.
sumber
Tidak dapat diakses langsung seperti di angular1 tetapi Anda dapat dengan mudah bermain dengan NgFormControl dan RxJS yang bisa diamati:
Posting blog ini menjelaskannya dengan jelas: http://blog.thoughtram.io/angular/2016/01/06/mengambil manfaat dariof-observables-in-angular2.html
Ini untuk autocomplete tetapi berfungsi semua skenario.
sumber
[...]
adalah target mengikat satu arah. Mengapa wadah dapat diberitahukanvalueChanges
? seharusnya tidak harus menjadi sth. suka(ngFormControl)="..."
?Anda dapat membuat RxJS (v.6) Dapat Diamati yang melakukan apa pun yang Anda suka.
view.component.html
view.component.ts
sumber
rsjs/Rx
, saya memiliki kesalahan ketika menggunakan impor seperti yang Anda tulis ... jadi dalam kasus saya sekarang:import { Observable } from 'rxjs/Rx';
import { Observable } from 'rxjs';
.pipe
panggilanpipe(debounceTime(300), distinctUntilChanged())
Bagi siapa pun yang menggunakan lodash, sangat mudah untuk mendebo fungsi apa pun:
lalu lemparkan sesuatu seperti ini ke template Anda:
sumber
Solusi dengan pelanggan inisialisasi langsung dalam fungsi acara:
Dan html:
sumber
Saya memecahkan ini dengan menulis dekorator debounce. Masalah yang dijelaskan dapat diselesaikan dengan menerapkan @debounceAccessor ke set accessor properti.
Saya juga telah menyediakan dekorator debounce tambahan untuk metode, yang dapat berguna untuk acara lain.
Ini membuatnya sangat mudah untuk melakukan debug properti atau metode. Parameternya adalah jumlah milidetik yang harus didebet ulang, 100 ms dalam contoh di bawah ini.
Dan ini kode untuk dekorator:
Saya menambahkan parameter tambahan untuk dekorator metode yang memungkinkan Anda memicu metode SETELAH penundaan debounce. Saya melakukan itu sehingga saya bisa menggunakannya misalnya ketika digabungkan dengan mouseover atau mengubah ukuran acara, di mana saya ingin menangkap terjadi pada akhir aliran acara. Namun dalam kasus ini, metode ini tidak akan mengembalikan nilai.
sumber
Kita dapat membuat arahan [debounce] yang menimpa fungsi viewToModelUpdate dari ngModel dengan yang kosong.
Kode Arahan
Bagaimana cara menggunakannya
sumber
File HTML:
File TS:
sumber
Solusi sederhana adalah dengan membuat arahan yang dapat Anda terapkan pada kontrol apa pun.
penggunaan akan
sumber
Angular 7
.Menghabiskan berjam-jam untuk hal ini, semoga saya dapat menghemat waktu bagi orang lain. Bagi saya pendekatan berikut untuk menggunakan
debounce
kontrol lebih intuitif dan lebih mudah dipahami bagi saya. Itu dibangun di atas solusi angular.io docs untuk pelengkapan otomatis tetapi dengan kemampuan bagi saya untuk mencegat panggilan tanpa harus bergantung pada pengikatan data ke DOM.Plunker
Skenario penggunaan kasus untuk ini mungkin memeriksa nama pengguna setelah itu diketik untuk melihat apakah seseorang telah mengambilnya, lalu memperingatkan pengguna.
Catatan: jangan lupa,
(blur)="function(something.value)
mungkin lebih masuk akal untuk Anda tergantung pada kebutuhan Anda.sumber
DebounceTime di Angular 7 dengan RxJS v6
Tautan Sumber
Demo Link
Di Template HTML
Dalam komponen
sumber
Anda juga bisa menyelesaikan ini dengan menggunakan dekorator, Misalnya dengan menggunakan dekorator debounce dari utils-decorator lib (
npm install utils-decorators
):sumber
Ini adalah solusi terbaik yang saya temukan sampai sekarang. Update
ngModel
padablur
dandebounce
seperti yang dipinjam dari https://stackoverflow.com/a/47823960/3955513
Kemudian dalam HTML:
Di
blur
model secara eksplisit diperbarui menggunakan javascript biasa.Contoh di sini: https://stackblitz.com/edit/ng2-debounce-working
sumber