angularjs-directive - AngularJS में एनजी-दोहराव के दायरे के साथ निर्देश अलग-अलग करें





angularjs-scope angularjs-ng-repeat (3)


सीधे अपने प्रश्नों का उत्तर देने से बचने के बिना, निम्नलिखित पहेली को देखें:

http://jsfiddle.net/dVPLM/

मुख्य बिंदु यह है कि कोणीय के पारंपरिक व्यवहार से लड़ने और बदलने की कोशिश करने के बजाय, आप अपने निर्देश को ng-repeat साथ काम करने के लिए तैयार कर सकते हैं क्योंकि इसे ओवरराइड करने का प्रयास करने के विरोध में।

आपके टेम्पलेट में:

    <name-row 
        in-names-list="names"
        io-selected="selected">
    </name-row>

आपके निर्देश में:

    template:
'        <ul>' +      
'            <li ng-repeat="name in inNamesList" ng-class="activeClass($index)" >' +
'                <a ng-click="setSelected($index)">' +
'                    {{$index}} - {{name.first}} {{name.last}}' +
'                </a>' +
'            </li>' +
'        </ul>'

आपके सवालों के जवाब में:

  • ng-repeat एक गुंजाइश बनाएगा, आपको वास्तव में इसे बदलने की कोशिश नहीं करनी चाहिए।
  • निर्देशों में प्राथमिकता केवल निष्पादन आदेश नहीं है - देखें: कोणीय जेएस: एचटीएमएल कंपाइलर संकलन के लिए आदेश कैसे व्यवस्थित करता है?
  • बटरंग में, यदि आप प्रदर्शन टैब की जांच करते हैं, तो आप प्रत्येक स्कोप के लिए अभिव्यक्तियों को देख सकते हैं, और जांच सकते हैं कि यह आपकी अपेक्षाओं से मेल खाता है या नहीं।

मेरे पास एक अलग-अलग दायरे के साथ निर्देश है (ताकि मैं अन्य स्थानों पर निर्देश का पुन: उपयोग कर सकूं), और जब मैं इस निर्देश का उपयोग ng-repeat साथ करता हूं, तो यह काम करने में विफल रहता है।

मैंने इस विषय पर सभी दस्तावेज और स्टैक ओवरफ़्लो उत्तर पढ़े हैं और मुद्दों को समझ लिया है। मेरा मानना ​​है कि मैंने सभी सामान्य गेटचा से बचा है।

तो मैं समझता हूं कि मेरा कोड ng-repeat निर्देश द्वारा बनाए गए दायरे के कारण विफल रहता है। मेरा अपना निर्देश एक अलग-अलग क्षेत्र बनाता है और माता-पिता के दायरे में किसी ऑब्जेक्ट के लिए दो-तरफा डेटा-बाइंडिंग करता है। मेरा निर्देश इस बाध्य चर के लिए एक नया ऑब्जेक्ट-वैल्यू असाइन करेगा और यह पूरी तरह से काम करता है जब मेरे निर्देश का उपयोग ng-repeat बिना किया जाता है (पैरेंट चर सही ढंग से अपडेट किया जाता है)। हालांकि, ng-repeat , असाइनमेंट ng-repeat दायरे में एक नया चर बनाता है और पैरेंट वैरिएबल में बदलाव नहीं दिखता है। यह सब मैंने जो पढ़ा है उसके आधार पर अपेक्षित है।

मैंने यह भी पढ़ा है कि जब किसी दिए गए तत्व पर कई निर्देश होते हैं, तो केवल एक गुंजाइश बनाई जाती है। और निर्देशों को लागू करने के क्रम में परिभाषित करने के लिए प्रत्येक निर्देश में priority निर्धारित की जा सकती है; निर्देश प्राथमिकता से क्रमबद्ध होते हैं और फिर उनके संकलन कार्यों को बुलाया जाता है ( http://docs.angularjs.org/guide/directive पर शब्द प्राथमिकता की खोज करें)।

तो मैं उम्मीद कर रहा था कि मैं यह सुनिश्चित करने के लिए प्राथमिकता का उपयोग कर सकता हूं कि मेरा निर्देश पहले चलता है और एक अलग-अलग-स्कोप बनाने के समाप्त होता है, और जब ng-repeat चलता है, तो यह एक ऐसा क्षेत्र बनाने के बजाय अलग-अलग-स्कोप का पुन: उपयोग करता है जो प्रोटोटाइपिक रूप से विरासत में प्राप्त होता है अभिभावक दायरा ng-repeat दस्तावेज बताता है कि निर्देश प्राथमिकता स्तर 1000 पर चलता है। यह स्पष्ट नहीं है कि 1 उच्च प्राथमिकता स्तर या निम्न प्राथमिकता स्तर है या नहीं। जब मैंने अपने निर्देश में प्राथमिकता स्तर 1 उपयोग किया, तो इससे कोई फर्क नहीं पड़ता, इसलिए मैंने 2000 की कोशिश की। लेकिन इससे चीजें बदतर हो जाती हैं: मेरे दो-तरफा बाइंडिंग undefined हो जाते हैं और मेरा निर्देश कुछ भी प्रदर्शित नहीं करता है।

मैंने अपनी समस्या दिखाने के लिए एक पहेली बनाई है । मैंने अपने निर्देश में priority सेटिंग की टिप्पणी की है। मेरे पास नाम ऑब्जेक्ट्स की एक सूची है और name-row नामक एक निर्देश है जो नाम ऑब्जेक्ट में पहला और अंतिम नाम फ़ील्ड दिखाता है। जब एक प्रदर्शित नाम क्लिक किया जाता है, तो मैं इसे मुख्य दायरे में एक selected चर सेट करना चाहता हूं। नामों की सरणी, selected चर दो-तरफा डेटा-बाइंडिंग का उपयोग करके name-row निर्देश में पारित किया जाता है।

मुझे पता है कि मुख्य दायरे में कार्यों को कॉल करके इसे कैसे काम करना है। मुझे यह भी पता है कि अगर selected है तो किसी अन्य वस्तु के अंदर है, और मैं बाहरी वस्तु से बांधता हूं, चीजें काम करती हैं। लेकिन मुझे इस समय उन समाधानों में दिलचस्पी नहीं है।

इसके बजाय, मेरे पास प्रश्न हैं:

  • मैं ng-repeat को ऐसे दायरे को बनाने से कैसे रोकूं जो प्रोटोटाइपिक रूप से मूल दायरे से प्राप्त होता है, और इसके बजाय यह मेरे निर्देश के अलग-अलग-स्कोप का उपयोग करता है?
  • मेरे निर्देश में प्राथमिकता स्तर 2000 क्यों काम नहीं कर रहा है?
  • बटरंग का उपयोग करना, क्या यह जानना संभव है कि किस प्रकार का दायरा उपयोग में है?



ठीक है, ऊपर दी गई कई टिप्पणियों के माध्यम से, मैंने भ्रम की खोज की है। सबसे पहले, स्पष्टीकरण के कुछ बिंदु:

  • ngRepeat आपके चुने हुए अलग-अलग दायरे को प्रभावित नहीं करता है
  • आपके निर्देश के गुणों पर उपयोग के लिए ngRepeat में पारित पैरामीटर प्रोटोटाइपिक रूप से विरासत वाले दायरे का उपयोग करते हैं
  • आपके निर्देश का काम नहीं करने का कारण अलग-अलग दायरे से कोई लेना देना नहीं है

यहां एक ही कोड का एक उदाहरण दिया गया है लेकिन निर्देश हटा दिए गए हैं:

<li ng-repeat="name in names"
    ng-class="{ active: $index == selected }"
    ng-click="selected = $index">
    {{$index}}: {{name.first}} {{name.last}}
</li>

यहां एक JSFiddle दिखा रहा है कि यह काम नहीं करेगा। आपको अपने निर्देश के समान सटीक परिणाम मिलते हैं।

यह क्यों काम नहीं करता है? क्योंकि AngularJS में scopes प्रोटोटाइपिक विरासत का उपयोग करें। आपके मूल दायरे पर selected मूल्य एक आदिम है । जावास्क्रिप्ट में, इसका मतलब यह है कि जब कोई बच्चा एक ही मूल्य निर्धारित करता है तो इसे ओवरराइट किया जाएगा। AngularJS scopes में एक सुनहरा नियम है: मॉडल मानों में हमेशा एक होना चाहिए . उनमे। यही है, वे कभी भी primitives नहीं होना चाहिए। अधिक जानकारी के लिए यह SO उत्तर देखें।

यहां एक तस्वीर है जो शुरू में स्कॉप्स की तरह दिखती है।

पहले आइटम पर क्लिक करने के बाद, अब स्कॉप्स इस तरह दिखते हैं:

ध्यान दें कि ngRepeat दायरे पर एक नई selected संपत्ति बनाई गई थी। नियंत्रक दायरा 003 परिवर्तित नहीं किया गया था।

आप शायद अनुमान लगा सकते हैं कि जब हम दूसरे आइटम पर क्लिक करते हैं तो क्या होता है:

तो आपकी समस्या वास्तव में ngRepeat के कारण नहीं होती है - यह AngularJS में सुनहरे नियम को तोड़ने के कारण होती है। इसे ठीक करने का तरीका केवल ऑब्जेक्ट प्रॉपर्टी का उपयोग करना है:

$scope.state = { selected: undefined };
<li ng-repeat="name in names"
    ng-class="{ active: $index == state.selected }"
    ng-click="state.selected = $index">
    {{$index}}: {{name.first}} {{name.last}}
</li>

यह एक दूसरा जेएसफ़िडल भी दिखाता है जो यह काम करता है।

यहां स्कॉप्स प्रारंभिक रूप से दिखते हैं:

पहले आइटम पर क्लिक करने के बाद:

यहां, वांछित के रूप में, नियंत्रक गुंजाइश प्रभावित किया जा रहा है।

साथ ही, यह साबित करने के लिए कि यह अभी भी एक अलग दायरे के साथ आपके निर्देश के साथ काम करेगा (क्योंकि, फिर से, इसमें आपकी समस्या से कोई लेना देना नहीं है), यहां इसके लिए एक JSFiddle भी है, दृश्य को वस्तु को प्रतिबिंबित करना चाहिए। आप ध्यान दें कि एकमात्र आवश्यक परिवर्तन एक आदिम के बजाय किसी ऑब्जेक्ट का उपयोग करना था।

शुरू में स्कॉप्स:

पहले आइटम पर क्लिक करने के बाद स्कॉप्स:

निष्कर्ष निकालने के लिए: एक बार फिर, आपकी समस्या अलग-अलग दायरे से नहीं है और यह ngRepeat कैसे काम करता है इसके साथ नहीं है। आपकी समस्या यह है कि आप एक ऐसे नियम को तोड़ रहे हैं जो इस समस्या को हल करने के लिए जाना जाता है। AngularJS में मॉडल हमेशा एक होना चाहिए .




मुझे बहुत गहन वीडियो मिले जो $watch , $apply , $digest और पाचन चक्रों को कवर करते हैं:

अवधारणाओं को समझाने के लिए उन वीडियो में उपयोग की जाने वाली कुछ स्लाइडें हैं (केवल अगर, उपर्युक्त लिंक हटा दिए गए हैं / काम नहीं कर रहे हैं)।

उपर्युक्त छवि में, "$ scope.c" नहीं देखा जा रहा है क्योंकि इसका उपयोग किसी भी डेटा बाइंडिंग (मार्कअप में) में नहीं किया जाता है। अन्य दो ( $scope.a और $scope.b ) देखे जाएंगे।

उपर्युक्त छवि से: संबंधित ब्राउज़र ईवेंट के आधार पर, एंगुलरजेएस घटना को कैप्चर करता है, पाचन चक्र करता है (परिवर्तनों के लिए सभी घड़ियों के माध्यम से जाता है), घड़ी कार्यों को निष्पादित करें और डीओएम अपडेट करें। यदि ब्राउज़र की घटनाएं नहीं हैं, तो डाइजेस्ट चक्र को $apply या $digest का उपयोग करके मैन्युअल रूप से ट्रिगर किया जा सकता $digest

$apply बारे में अधिक $apply और $digest :





angularjs angularjs-directive angularjs-scope angularjs-ng-repeat