2016-05-20 8 views
13

ले लिया है कि क्या जांच करने के लिए मैं क्या
कर रहा हूँ मैं एक घटक छुपाता है कि/शो एक सरल बूलियन के आधार पर *ngIf का उपयोग कर सकते है। जब घटक दिखाई देता है तो मैं अपने टेम्पलेट के भीतर एक बच्चे तत्व पर ध्यान केंद्रित करना चाहता हूं।कैसे ngIf प्रभाव

समस्या
अगर मैं बूलियन मान घटक सही ढंग से पता चलता है, लेकिन अगर मैं तो कोशिश करते हैं और this._elRef.nativeElement.querySelector("div#test") का उपयोग कर बच्चे तत्व के लिए संदर्भ मिल यह सिर्फ वापस null आता है फ्लिप। अगर मैं कुछ सेकंड प्रतीक्षा करता हूं तो वही कोड तत्व के संदर्भ को वापस लौटाएगा जैसा कि मैंने अपेक्षित था।

अटकलें
मैं यह सोचते हैं रहा हूँ बूलियन कोणीय flipping के बाद नव दिखाई घटक प्रकट करने के लिए एक पूरे के प्रतिपादन चक्र के माध्यम से चला जाता है कि और कहा कि इस समय तक समाप्त नहीं हुआ है मैं अगली पंक्ति में querySelector() लागू होते हैं।


जानना मैं अपनी पसंद का तो मैं क्या सोच रहा हूँ है, मैं कैसे यकीन है कि मेरी ngIf प्रभाव ले लिया है और तत्वों डोम में अपने कर रहे हैं का चयन किया जाना हो सकता है?
क्या ngIf के लिए कॉलबैक जैसी कोई चीज़ है या क्या मैं दृश्य को अपडेट करने और उस से कॉलबैक प्राप्त करने के लिए मजबूर कर सकता हूं?

मुझे उम्मीद है कि यह समझ में आता है। यह एक लंबा दिन रहा है (लंबा सप्ताह) और मैं बहुत थक गया हूँ।
धन्यवाद सभी

यह मदद करता है, मैं Angular2 v2.0.0-beta.15

उत्तर

16

उपयोग कर रहा हूँ आप true को बूलियन मान फ्लिप और कोड की अगली पंक्ति में आप के लिए एक संदर्भ प्राप्त करने की कोशिश करते हैं, तो घटक या डीओएम तत्व NgIf द्वारा नियंत्रित ... अच्छी तरह से, वह घटक या DOM तत्व अभी तक मौजूद नहीं है। कोणीय आपके कोड के साथ समानांतर में नहीं चलता है। आपके जावास्क्रिप्ट कॉलबैक को समाप्त करना है, फिर कोणीय (पता लगाने का पता चलता है) चलता है, जो बूलियन मान परिवर्तन को नोटिस करेगा और घटक या डीओएम तत्व बनायेगा और इसे डोम में डालें।

अपनी समस्या को ठीक करने के लिए, बूलियन मान को फ़्लिप करने के बाद setTimeout(callbackFn, 0) पर कॉल करें। यह को JavaScript message queue में जोड़ता है। यह सुनिश्चित करेगा कि कोणीय (परिवर्तन पहचान) आपके कॉलबैक फ़ंक्शन से पहले चलता है। इसलिए, जब आपका callbackFn निष्पादित करता है, तो जिस तत्व को आप फोकस करना चाहते हैं वह अब मौजूद होना चाहिए। setTimeout(..., 0) का उपयोग करना सुनिश्चित करता है कि JavaScript event loop की अगली बारी में आपका callbackFn कॉल हो जाता है।

setTimeout(..., 0) का उपयोग करने की यह तकनीक AfterView* hooks पर चर्चा करते समय लाइफसाइकल हुक देव गाइड में उपयोग की जाती है।यदि आप अधिक जानकारी की आवश्यकता

यहाँ, कुछ अन्य उदाहरण हैं:

+0

कैसे मजबूत 'setTimeout()' समाधान है? इसने 0 की देरी का उपयोग करके मेरी समस्या हल कर दी है लेकिन यह हैकी की तरह लगता है। क्या टाइमआउट शेष कोड से पूरी तरह से अलग नहीं है और इसलिए ऐसा नहीं हो सकता है जब अपडेट देखने के लिए लंबे समय तक आवश्यकता होती है और देरी में वृद्धि की आवश्यकता होगी? – popClingwrap

+0

@popClingwrap, कृपया मेरे उत्तर संपादन देखें। मैंने कुछ और विवरण जोड़ने की कोशिश की। 'SetTimeout() 'का उपयोग करना हैकी बिल्कुल नहीं है, और यह मजबूत है। कुछ कोड के निष्पादन को रोकने के लिए यह सामान्य जावास्क्रिप्ट तरीका है। इस मामले में, जब तक कोणीय डीओएम तत्व बनाता है तब तक हमें फोकस को स्थगित करने की आवश्यकता होती है। मामलों को प्रस्तुत करने के लिए "लंबा नहीं" होना चाहिए। एंगुलर चेंज डिटेक्शन बनाता है कि जो कुछ भी डीओएम बदलता है उसे प्रस्तुत करने के लिए ईवेंट लूप का हमेशा एक मोड़ होना चाहिए। –

+0

यह कुछ दिलचस्प चीजें हैं जिन्हें मैं जावास्क्रिप्ट के वास्तविक झटके से पहले नहीं जानता था। अतिरिक्त विस्तार के लिए धन्यवाद, जिसने वास्तव में मदद की और इसे पढ़ने के लिए नई सामग्री का पूरा भार दिया और :) – popClingwrap

4

यह सवाल काफी पुराना है, और वर्तमान समाधान उस समय उपलब्ध नहीं हो सकता है।

setTimeout() विधि पूरी तरह व्यवहार्य है, लेकिन इसमें महत्वपूर्ण गिरावट आई है। यदि आप एक तत्व को स्थिति देने के लिए बस एक वर्ग सेट करते हैं, जैसे मैंने किया, तो आपको एक अजीब परिणाम मिलता है, क्योंकि कोड कोणीय पाश के बाद निष्पादित होता है।

ChangeDetectorRef का उपयोग करके परिणाम उत्पन्न होता है जो कूद नहीं जाता है।

बजाय इस की:

class Foo { 
    public isDisplayed = false; 

    constructor(@Inject(ElementRef) private elementRef: ElementRef) { 
    } 

    public someMethod(): void { 
    this.isDisplayed = true; 
    setTimeout(() => { 
     const child = this.elementRef.nativeElement.querySelector('.child-element'); 
     // ... 
    }); 
    } 
} 

आप ऐसा कर सकता है:

class Foo { 
    public isDisplayed = false; 

    constructor(@Inject(ElementRef) private elementRef: ElementRef, 
       @Inject(ChangeDetectorRef) private changeDetectorRef: ChangeDetectorRef) { 
    } 

    public someMethod(): void { 
    this.isDisplayed = true; 
    this.changeDetectorRef.detectChanges(); 
    const child = this.elementRef.nativeElement.querySelector('.child-element'); 
    // ... 
    } 
} 
+0

बहुत अच्छा लगा। आप कोणीय परिवर्तन पहचान मैन्युअल रूप से ट्रिगर करते हैं, फिर आप अपने तत्व को स्थिति देते हैं - ब्राउज़र वास्तव में प्रस्तुत करने से पहले। –

संबंधित मुद्दे