RC.5 के लिए अद्यतन किया गया
कोणीय 2 के साथ हम RxJS ऑपरेटर के debounceTime()
नियंत्रण फॉर्म के valueChanges
अवलोकन पर उपयोग कर बहस कर सकते हैं :
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
ऊपर दिए गए कोड में उदाहरण भी शामिल है कि विंडो को थ्रॉटल कैसे करना है, जैसा कि नीचे टिप्पणी में @albanx द्वारा पूछा गया है।
यद्यपि उपरोक्त कोड संभवतः ऐसा करने का कोणीय-तरीका है, लेकिन यह कुशल नहीं है। हर कीस्ट्रोके और हर आकार की घटना, भले ही वे विवादित और थ्रॉटल की जाती हैं, परिणाम में परिवर्तन का पता चलता है। दूसरे शब्दों में, डिबगिंग और थ्रॉटलिंग यह प्रभावित नहीं करते हैं कि कितनी बार डिटेक्शन रन बदलते हैं । (मुझे टोबियास बॉश की एक GitHub टिप्पणी मिली जो इसकी पुष्टि करती है।) आप इसे तब देख सकते हैं जब आप प्लंकर चलाते हैं और आप देखते हैं कि ngDoCheck()
इनपुट बॉक्स में टाइप करते समय या विंडो का आकार बदलने पर आपको कितनी बार बुलाया जा रहा है। (आकार बदलने की घटनाओं को देखने के लिए एक अलग विंडो में प्लंकर चलाने के लिए नीले "x" बटन का उपयोग करें।)
एक अधिक कुशल तकनीक आरएक्सजेएस ऑब्जर्वबल्स को खुद को घटनाओं से, एंगुलर के "ज़ोन" के बाहर बनाने के लिए है। इस तरह, परिवर्तन का पता लगाने को हर बार ईवेंट आग नहीं कहा जाता है। फिर, अपनी सदस्यता कॉलबैक विधियों में, मैन्युअल रूप से परिवर्तन का पता लगाने को ट्रिगर करें - अर्थात, परिवर्तन का पता लगने पर आप नियंत्रण करते हैं:
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
मैं यह सुनिश्चित करने के ngAfterViewInit()
बजाय उपयोग करता हूं ngOnInit()
कि inputElRef
यह परिभाषित है।
detectChanges()
इस घटक और इसके बच्चों पर परिवर्तन का पता लगाएंगे। यदि आप रूट कंपोनेंट से परिवर्तन का पता लगाना चाहते हैं (यानी, पूर्ण परिवर्तन का पता लगाने के लिए जाँच करें) तो ApplicationRef.tick()
इसके बजाय उपयोग करें । (मैंने ApplicationRef.tick()
प्लंकर में टिप्पणियों में एक कॉल लगाई।) ध्यान दें कि कॉलिंग tick()
का कारण होगा ngDoCheck()
।