आपकी समस्या का समाधान करने के लिए, आप बस हो जाते हैं और प्रत्येक का आकार परिवर्तन घटना के बाद एक घटक संपत्ति में div
के आकार की दुकान, और टेम्पलेट में है कि संपत्ति का उपयोग करने की जरूरत है। इस तरह, मूल्य निरंतर रहेगा जब परिवर्तन का दूसरा दौर देव मोड में चलता है।
मैं भी अपने टेम्पलेट (window:resize)
जोड़ने के बजाय @HostListener
का उपयोग करें। div
का संदर्भ प्राप्त करने के लिए हम @ViewChild
का उपयोग करेंगे। और प्रारंभिक मान सेट करने के लिए हम जीवन चक्र हुक ngAfterViewInit()
का उपयोग करेंगे।
import {Component, ViewChild, HostListener} from '@angular/core';
@Component({
selector: 'my-app',
template: `<div #widgetParentDiv class="Content">
<p>Sample widget</p>
<table><tr>
<td>Value1</td>
<td *ngIf="divWidth > 350">Value2</td>
<td *ngIf="divWidth > 700">Value3</td>
</tr>
</table>`,
})
export class AppComponent {
divWidth = 0;
@ViewChild('widgetParentDiv') parentDiv:ElementRef;
@HostListener('window:resize') onResize() {
// guard against resize before view is rendered
if(this.parentDiv) {
this.divWidth = this.parentDiv.nativeElement.clientWidth;
}
}
ngAfterViewInit() {
this.divWidth = this.parentDiv.nativeElement.clientWidth;
}
}
बहुत बुरा है कि काम नहीं करता। हम के बाद यह जांच की गई
अभिव्यक्ति बदल गया है मिलता है। पिछला मान: 'झूठा'। वर्तमान मूल्य: 'सत्य'।
त्रुटि हमारे NgIf
भाव के बारे में शिकायत कर रहा है - पहली बार इसे चलाता divWidth
0 है, तो ngAfterViewInit()
रन है और 0 के अलावा कुछ करने के लिए मूल्य बदल जाता है, तो परिवर्तन का पता लगाने रन के 2 दौर (देव में मोड)। शुक्र है, वहाँ एक आसान/जाना जाता समाधान है, और यह एक बार की ही मुद्दा है, नहीं ओपी में की तरह एक सतत मुद्दा है:
ngAfterViewInit() {
// wait a tick to avoid one-time devMode
// unidirectional-data-flow-violation error
setTimeout(_ => this.divWidth = this.parentDiv.nativeElement.clientWidth);
}
ध्यान दें कि यह तकनीक, एक टिक इंतजार कर के यहाँ से प्रलेखित है: https://angular.io/docs/ts/latest/cookbook/component-communication.html#!#parent-to-view-child
अक्सर, ngAfterViewInit()
और ngAfterViewChecked()
में हमें setTimeout()
चाल को नियोजित करने की आवश्यकता होगी क्योंकि घटक के दृश्य के बाद इन विधियों को बुलाया जाता है।
यहां एक काम कर रहा है plunker।
हम इसे बेहतर बना सकते हैं। मुझे लगता है कि हमें आकार बदलने की घटनाओं को थ्रॉटल करना चाहिए जैसे कि कोणीय परिवर्तन का पता लगाना, हर 100-250 एमएमएस कहता है, बल्कि हर बार एक आकार बदलने का आयोजन होता है। जब उपयोगकर्ता विंडो का आकार बदल रहा है, तो ऐप को आलसी होने से रोकना चाहिए, क्योंकि अभी, प्रत्येक आकार बदलने की घटना में परिवर्तन का पता लगाने का कारण बनता है (देव मोड में दो बार)।
ngDoCheck() {
console.log('change detection');
}
observables कर सकते हैं आसानी से थ्रॉटल घटनाओं, इसलिए बजाय @HostListener
का उपयोग कर आकार परिवर्तन घटना के लिए बाध्य करने के लिए की, हम एक नमूदार पैदा हो जाएगी:
Observable.fromEvent(window, 'resize')
.throttleTime(200)
.subscribe(_ => this.divWidth = this.parentDiv.nativeElement.clientWidth);
आप पिछले plunker के लिए निम्न विधि जोड़कर इस की पुष्टि कर सकते
यह काम करता है, लेकिन ... इसके साथ प्रयोग करते समय, मैंने कुछ बहुत ही रोचक खोज की ... भले ही हम आकार बदलने की घटना को थ्रॉटल करते हैं, फिर भी एंजुलर चेंज डिटेक्शन तब भी चलता है जब एक आकार बदलने का आयोजन होता है। यानी, थ्रॉटलिंग इस बात को प्रभावित नहीं करती है कि पहचान कितनी बार बदलती है। (टोबीस बॉश ने इसकी पुष्टि की: https://github.com/angular/angular/issues/1773#issuecomment-102078250।)
यदि घटना थ्रॉटल समय से गुज़रती है तो मैं केवल रन को बदलने के लिए बदलना चाहता हूं। और मुझे इस घटक पर चलाने के लिए केवल परिवर्तन पहचान की आवश्यकता है।
constructor(private ngzone: NgZone, private cdref: ChangeDetectorRef) {}
ngAfterViewInit() {
// set initial value, but wait a tick to avoid one-time devMode
// unidirectional-data-flow-violation error
setTimeout(_ => this.divWidth = this.parentDiv.nativeElement.clientWidth);
this.ngzone.runOutsideAngular(() =>
Observable.fromEvent(window, 'resize')
.throttleTime(200)
.subscribe(_ => {
this.divWidth = this.parentDiv.nativeElement.clientWidth;
this.cdref.detectChanges();
})
);
}
यहाँ एक काम कर plunker है: समाधान कोणीय क्षेत्र के बाहर नमूदार बनाने के लिए है, तो मैन्युअल रूप से सदस्यता कॉलबैक अंदर परिवर्तन का पता लगाने कहते हैं।
प्लंकर में मैंने counter
जोड़ा है कि मैं जीवन चक्र हुक ngDoCheck()
का उपयोग करके प्रत्येक परिवर्तन पहचान चक्र को बढ़ाता हूं। आप देख सकते हैं कि इस विधि को – नहीं कहा जा रहा है काउंटर मान आकार बदलने पर ईवेंट नहीं बदलता है।
detectChanges()
इस घटक और उसके बच्चों पर परिवर्तन का पता चलाएगा। यदि आप रूट घटक से परिवर्तन पहचान को चलाएंगे (यानी, एक पूर्ण परिवर्तन पहचान जांच चलाएं) तो इसके बजाय ApplicationRef.tick()
का उपयोग करें (यह प्लंकर में टिप्पणी की गई है)। ध्यान दें कि tick()
कहने के लिए ngDoCheck()
का कारण बन जाएगा।
यह एक अच्छा सवाल है।मैंने अलग-अलग समाधानों की कोशिश करने में बहुत समय बिताया और मैंने बहुत कुछ सीखा। इस सवाल को पोस्ट करने के लिए धन्यवाद।
मुझे यकीन है कि मैं समझता हूँ कि आप क्या ढूंढ रहे हैं ... और अभी तक नहीं कर रहा हूँ ... सबसे पहले, तुम क्यों लिख सकता हूँ '* ngif =" ... 'यह एक सही वाक्यविन्यास हो सकता है (हालांकि इसे जांचने के लिए परेशान नहीं किया गया), लेकिन मुझे यकीन है कि 'ng-if =" ... "काम करता है जब परीक्षण की स्थिति कोणीय के दायरे में होती है इस प्रकार, आप इसे बदलने की कोशिश कर सकते हैं और अपनी इच्छित इच्छा (यानी चौड़ाई बनाम थ्रेसहोल्ड) को सक्षम करने के लिए '$ स्कोप' वैरिएबल अपडेट किया जा रहा है। – FDavidov
हाय डेविड, आपकी टिप्पणी के लिए धन्यवाद। मैं केवल नया हूं कोणीय/कोणीय 2, लेकिन मुझे लगता है कि एनजी-अगर और $ स्कोप केवल अंगुलर में उपयोग किया जाता है और इसे कोणीय 2 में बदल दिया गया है। नीचे की रेखा में लिंक यदि आप रुचि रखते हैं तो वह मेरे उद्देश्य को बताता है। चीयर्स –
ओउप्स !!! "2" मिस गया। माफ़ कीजिये। मैं समय के लिए कोणीय के साथ रहूँगा :-)। – FDavidov