2013-03-13 20 views
18

के साथ निर्देश और नियंत्रक के बीच दायरे को सही ढंग से बाध्य करने के लिए कैसे मैं anugularJS के साथ एक एन-स्तरीय पदानुक्रमित अनॉर्डर्ड सूची उत्पन्न करने की कोशिश कर रहा हूं, और सफलतापूर्वक ऐसा करने में सक्षम हूं। लेकिन अब, मुझे निर्देश और नियंत्रक के बीच दायरे के मुद्दे हैं। मुझे निर्देश टेम्पलेट में एनजी-क्लिक के माध्यम से बुलाए गए फ़ंक्शन के भीतर माता-पिता की एक स्कोप प्रॉपर्टी बदलने की आवश्यकता है।कोणीय जेएस

http://jsfiddle.net/ahonaker/ADukg/2046/ देखें - यहाँ जे एस

var app = angular.module('myApp', []); 

//myApp.directive('myDirective', function() {}); 
//myApp.factory('myService', function() {}); 

function MyCtrl($scope) { 
    $scope.itemselected = "None"; 
    $scope.organizations = { 
     "_id": "SEC Power Generation", 
     "Entity": "OPUNITS", 
     "EntityIDAttribute": "OPUNIT_SEQ_ID", 
     "EntityID": 2, 
     "descendants": ["Eastern Conf Business Unit", "Western Conf Business Unit", "Atlanta", "Sewanee"], 
     children: [{ 
      "_id": "Eastern Conf Business Unit", 
      "Entity": "", 
      "EntityIDAttribute": "", 
      "EntityID": null, 
      "parent": "SEC Power Generation", 
      "descendants": ["Lexington", "Columbia", "Knoxville", "Nashville"], 
      children: [{ 
       "_id": "Lexington", 
       "Entity": "OPUNITS", 
       "EntityIDAttribute": "OPUNIT_SEQ_ID", 
       "EntityID": 10, 
       "parent": "Eastern Conf Business Unit" 
      }, { 
       "_id": "Columbia", 
       "Entity": "OPUNITS", 
       "EntityIDAttribute": "OPUNIT_SEQ_ID", 
       "EntityID": 12, 
       "parent": "Eastern Conf Business Unit" 
      }, { 
       "_id": "Knoxville", 
       "Entity": "OPUNITS", 
       "EntityIDAttribute": "OPUNIT_SEQ_ID", 
       "EntityID": 14, 
       "parent": "Eastern Conf Business Unit" 
      }, { 
       "_id": "Nashville", 
       "Entity": "OPUNITS", 
       "EntityIDAttribute": "OPUNIT_SEQ_ID", 
       "EntityID": 4, 
       "parent": "Eastern Conf Business Unit" 
      }] 
     }] 
    }; 

    $scope.itemSelect = function (ID) { 
     $scope.itemselected = ID; 
    } 
} 

app.directive('navtree', function() { 
    return { 
     template: '<ul><navtree-node ng-repeat="item in items" item="item" itemselected="itemselected"></navtree-node></ul>', 
     restrict: 'E', 
     replace: true, 
     scope: { 
      items: '=' 
     } 
    }; 
}); 

app.directive('navtreeNode', function ($compile) { 
    return { 
     restrict: 'E', 
     template: '<li><a ng-click="itemSelect(item._id)">{{item._id}} - {{itemselected}}</a></li>', 
     scope: { 
      item: "=", 
      itemselected: '=' 
     }, 
     controller: 'MyCtrl', 
     link: function (scope, elm, attrs) { 
      if ((angular.isDefined(scope.item.children)) && (scope.item.children.length > 0)) { 
       var children = $compile('<navtree items="item.children"></navtree>')(scope); 
       elm.append(children); 
      } 
     } 
    }; 
}); 

है और यहाँ एचटीएमएल

<div ng-controller="MyCtrl"> 
    Selected: {{itemselected}} 

    <navtree items="organizations.children"></navtree> 
</div> 

नोट सूची मॉडल से उत्पन्न होता है है। और ng-click पैरेंट स्कोप प्रॉपर्टी (आइटम चयन) सेट करने के लिए फ़ंक्शन को कॉल करता है, लेकिन परिवर्तन केवल स्थानीय रूप से होता है। अपेक्षित व्यवहार, जब मैं किसी आइटम पर क्लिक करता हूं, तो यह है कि "चयनित: कोई नहीं" को "चयनित: xxx" में बदलना चाहिए जहां xxx वह आइटम है जिसे क्लिक किया गया था।

क्या मैं मूल दायरे और निर्देश के बीच संपत्ति को बाध्य नहीं कर रहा हूं? मैं संपत्ति के दायरे में संपत्ति परिवर्तन कैसे पास करूं?

आशा है कि यह स्पष्ट है।

किसी भी मदद के लिए अग्रिम धन्यवाद।

+1

स्टैक ओवरव्लो में आपका स्वागत है! यदि आप अंत के पास एक वास्तविक प्रश्न के रूप में इसे दोहराते हैं तो यह आपकी पोस्ट को बेहतर बना सकता है। –

उत्तर

18

कृपया इस काम कर बेला पर एक नजर है, http://jsfiddle.net/eeuSv/

मैं क्या navtree-node निर्देश के अंदर माता पिता नियंत्रक की आवश्यकता होती है, और कॉल एक सदस्य समारोह है कि नियंत्रक में परिभाषित किया गया था। सदस्य फ़ंक्शन setSelected है। कृपया ध्यान दें कि इसकी this.setSelected और $scope.setSelected नहीं है। फिर navtree-node स्कोप विधि itemSelect परिभाषित करें। जब आप एंकर टैग पर क्लिक करते हैं, तो यह विधि navtree-node स्कोप पर कॉल करेगा। यह मंथ चयनित आईडी को पास करने वाले नियंत्रकों सदस्य विधि setSelected पर कॉल करेगा।

scope.itemSelect = function(id){ myGreatParentControler.setSelected(id) }

+1

धन्यवाद राजकमल .... मैंने यह काम किया है। मैं अभी भी 'आवश्यकता: "^ ngController पर उलझन में हूं" 'ngController कहां से आता है? – user2165994

+3

सामान्य शब्दों में यह कहने के लिए, 'आवश्यकताएँ: "^ ngController" 'कथन उन मूल तत्वों को ढूंढता है जिन पर नियंत्रक परिभाषित किया गया है। चूंकि हमने 'navtree' के ऊपर नियंत्रक' MyCtrl' को परिभाषित किया है, इसलिए यह चौथे पैरामीटर के रूप में नेविगेशन-नोड निर्देश के लिंकिंग फ़ंक्शन को पास कर दिया गया है। आप निर्देशक परिभाषा ऑब्जेक्ट शीर्षक के तहत http://docs.angularjs.org/guide/directive में इसके बारे में पढ़ सकते हैं। यहां उन्होंने विकल्पों को परिभाषित किया है। – rajkamal

+3

+1। अच्छा लगा। मैंने किसी और को एसओ पर एक उदाहरण नहीं देखा है जिसका उपयोग 'आवश्यकता:'^ngController'' था। मैंने देखा है कि अन्य सभी उदाहरणों में ngModel या किसी अन्य निर्देशक नियंत्रक की आवश्यकता होती है। –

3

ऐसा इसलिए हो सकता है क्योंकि प्रत्येक निर्देश अपना स्वयं का दायरा बनाता है (वास्तव में आप उन्हें ऐसा करने के लिए कहते हैं)।
आप निर्देश here, विशेष रूप से अध्याय "लेखन निर्देश (लंबा संस्करण)" के बारे में अधिक पढ़ सकते हैं।

गुंजाइश - करने के लिए सेट करते हैं: - फिर एक नया गुंजाइश इस निर्देश के लिए बनाया जाएगा

सच। यदि उसी तत्व पर एकाधिक निर्देश एक नए दायरे का अनुरोध करते हैं, तो केवल एक नया दायरा बनाया गया है। नया स्कोप नियम टेम्पलेट के रूट के लिए लागू नहीं होता है क्योंकि टेम्पलेट की जड़ हमेशा एक नया गुंजाइश प्राप्त करती है।

{} (ऑब्जेक्ट हैश) - फिर एक नया 'पृथक' दायरा बनाया गया है। 'पृथक' दायरा सामान्य दायरे से अलग है जिसमें यह प्रोटोटाइपिक रूप से मूल दायरे से प्राप्त नहीं होता है। यह उपयोगी है जब पुन: प्रयोज्य घटकों का निर्माण, जो गलती से पढ़ा नहीं जाना चाहिए या मूल दायरे में डेटा संशोधित करना चाहिए।

तो आपके द्वारा किए गए परिवर्तन MyCtrl स्कोप में प्रतिबिंबित नहीं होते हैं क्योंकि प्रत्येक निर्देश का अपना 'पृथक' दायरा होता है।

यही कारण है कि एक क्लिक केवल स्थानीय $scope.itemselected चर बदलता है और उनमें से सभी 'नहीं' बदलता है।

+0

धन्यवाद maxdec, लेकिन निर्देश को पदानुक्रम के माध्यम से लगातार चलने में सक्षम होने के लिए अपने दायरे की आवश्यकता है। मैं दोनों दुनिया के सर्वश्रेष्ठ कैसे प्राप्त करूं: पदानुक्रम के लिए स्थानीय दायरा और अन्य गुणों के लिए अभिभावक के दायरे तक पहुंच? मैंने उस दस्तावेज़ को पढ़ा है जिसे आप विज्ञापन मतली से लिंक करते हैं और सोचा कि मैं समझ गया हूं, विशेष रूप से बिट "= या = attr - स्थानीय स्कोप संपत्ति और अभिभावक स्कोप संपत्ति के बीच द्वि-दिशात्मक बाध्यकारी सेट अप करें ..." और "कोई भी परिवर्तन parentModel को स्थानीय मॉडल में प्रतिबिंबित किया जाएगा और स्थानीय मॉडल में कोई भी परिवर्तन मूल मॉडल में प्रतिबिंबित होगा। " लेकिन मैं सिर्फ यह काम नहीं कर सकता। – user2165994

+0

@ user2165994, "मैं दोनों दुनिया के सर्वश्रेष्ठ कैसे प्राप्त करूं: पदानुक्रम के लिए स्थानीय दायरा और अन्य गुणों के लिए मूल दायरे तक पहुंच?" - 'स्कोप: सत्य' का उपयोग करें। आपके निर्देश को इसका अपना दायरा मिलेगा [प्रोटोटाइपिक रूप से विरासत] (http://stackoverflow.com/questions/14049480/what-are-the-nuances-of-scope-prototypal-prototypical-inheritance-in-angularjs/14049482#14049482) माता-पिता के दायरे से। तो आप अपनी खुद की संपत्तियों, और/या संदर्भ मूल गुणों को परिभाषित कर सकते हैं। यदि आपको किसी मूल संपत्ति को लिखने की आवश्यकता है, तो सुनिश्चित करें कि यह एक ऑब्जेक्ट प्रॉपर्टी है (उदा।, 'Model.prop1'), एक आदिम ('prop1') नहीं। –

11

मैक्सडेक सही है, इसे स्कॉइंग के साथ करना है। दुर्भाग्यवश, यह एक ऐसा मामला है जो जटिल है कि AngularJS दस्तावेज़ शुरुआती (जैसे खुद) के लिए गलत-अग्रणी हो सकते हैं।

चेतावनी: मेरे लिए इसे थोड़ा सा हवादार होने के लिए खुद को ब्रेस करें क्योंकि मैं इसे समझाने का प्रयास करता हूं। अगर आप कोड देखना चाहते हैं, तो इस JSFiddle पर जाएं।मुझे AngularJS के बारे में सीखने में अमूल्य egghead.io वीडियो भी मिल गए हैं।

यहां समस्या की मेरी समझ है: आपके पास निर्देशों का एक पदानुक्रम है (navtree, navitem) और आप रूट नियंत्रक को "पेड़ ऊपर" नेविटम से जानकारी पास करना चाहते हैं। कोणीय जेएस, सामान्य रूप से अच्छी तरह से लिखित जावास्क्रिप्ट की तरह, आपके चर के दायरे के बारे में सख्त होने के लिए स्थापित किया गया है, ताकि आप गलती से पृष्ठ पर चल रहे अन्य स्क्रिप्ट को गड़बड़ न करें।

वहाँ कोणीय में एक विशेष वाक्य रचना (&) देता है कि आप दोनों एक अलग गुंजाइश बना सकते हैं और माता-पिता गुंजाइश पर एक समारोह फोन:

// in your directive 
scope: { 
    parentFunc: '&' 
} 

अब तक तो अच्छा। हालात मुश्किल हो आप निर्देशों के कई स्तरों है जब, क्योंकि आप अनिवार्य रूप से निम्न कार्य करना चाहते हैं:

  1. मॉडल
  2. एक मध्य स्तर के निर्देश जड़ नियंत्रक कि एक चर को स्वीकार करता है में एक समारोह है और अद्यतन
  3. एक बच्चे स्तर के निर्देश है कि जड़ नियंत्रक

समस्या है के साथ संवाद कर सकते हैं, बच्चों के स्तर के निर्देश जड़ नियंत्रक नहीं देख सकता।

पहले:: अपने जड़ नियंत्रक में एक समारोह में एक समारोह (जो रूट दृश्य नियंत्रक के के संदर्भ में है देता है कि है मेरी समझ में एक "श्रृंखला" अपने निर्देश संरचना में इस प्रकार है कि के रूप में कार्य स्थापित करने के लिए है कि आप है गुंजाइश):

$scope.selectFunctionRoot = function() { 
    return function (ID) { 
     $scope.itemselected = ID; 
    } 
} 

दूसरा: मध्य स्तर के निर्देश सेट करें यह खुद चुनिंदा समारोह (जो यह बच्चे को पारित करेंगे) निम्न की तरह कुछ देता है है।

// in the link function of the mid-level directive. the 'navtreelist' 
scope.selectFunctionMid = function() { 
    // if we don't capture our mid-level scope, then when we call the function in the navtreeNode it won't be able to find the mid-level-scope's functions    
    _scope = scope; 
    return function (item_id) { 
     console.log('mid'); 
     console.log(item_id); 

     // this will be the "root" select function 
     parentSelectFunction = _scope.selectFunction(); 
     parentSelectFunction(item_id); 
    }; 
}; 

तीसरा: में नोटिस कैसे हम मध्य स्तर के निर्देश के दायरे बंद को बचाने के लिए है, क्योंकि जब इस कोड को वास्तव में क्रियान्वित किया जाता है, यह बच्चे स्तर के निर्देश के संदर्भ में किया जाएगा बच्चे स्तर के निर्देश (navtreeNode) ng-click एक स्थानीय समारोह है, जो होगा, बारी में, "ऊपर श्रृंखला फोन" रूट नियंत्रक से सभी तरह से कॉल करने के लिए एक समारोह के लिए बाध्य:

// in 'navtreeNode' link function 
scope.childSelect = function (item_id) { 
    console.log('child'); 
    console.log(item_id); 

    // this will be the "mid" select function 
    parentSelectFunction = scope.selectFunction(); 
    parentSelectFunction(item_id); 
}; 

यहाँ अपडेट हो जाता है fork of your JSFiddle, कोड में टिप्पणी है।

+0

अच्छा anwser! मैंने कुछ सीखा – maxdec

+0

नियंत्रक और निर्देश के बीच, दायरे के दो-तरफा बाध्यकारी का उपयोग करके एक सामान्य कार्य साझा करने पर उत्कृष्ट उत्तर। धन्यवाद! – Alex