2013-03-13 16 views
28

कोणीय जेएस में कोणीय डॉक्स में उल्लिखित डीओएम आधारित नियंत्रक विरासत है।कोणीय जेएस नियंत्रक विरासत

<div ng-controller="BaseController"> 
    <p>Base Controller Value: {{value}}</p> 
    <button ng-click="updateValue()">Update In Base</button> 
    <div ng-controller="DerivedController"> 
     <p>Derived Controller Value: {{value}}</p> 
     <button ng-click="updateValue()">Update In Derived</button> 
    </div> 
</div> 

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

यहाँ एक बेला एक ही उदाहरण का प्रदर्शन है: http://jsfiddle.net/6df6S/1/

कैसे एक स्तर पर परिवर्तन तत्काल बच्चे और वर्तमान क्षेत्र के तत्काल माता-पिता के लिए प्रचार करने के लिए बनाया जा सकता है।

हम

$ दायरे का उपयोग करके यह लागू कर सकते हैं। $ घड़ी

इसमें या ऐसे किसी पर नजर रखने वालों का उपयोग किए बिना ऐसा करने के लिए कोई तरीका है?

संपादित करें 1:।

$ दायरे का उपयोग करके $ यहाँ देख मैं क्या मतलब

$scope.$watch("value", function() { 
    $scope.$broadcast("childChangeListener"); //Downwards to all children scopes 
    $scope.$emit("parentChangeListener"); //Upwards to all parent scopes 
}); 

मैं तरीकों से मूल्य ऐसे तंत्र का उपयोग किए बिना सभी कार्यक्षेत्रों में अपडेट जायेगा लिए देख रहा था है । $broadcast

प्रलेखन से::

+0

में के बारे में अधिक का उपयोग करें $ rootScope –

+0

वहाँ $ rootScope में गुण और विधियों डाल करने के लिए बिना $ गुंजाइश साझा करने के लिए कोई तरीका है? –

+4

कृपया $ rootScope का उपयोग न करें। नियंत्रकों के बीच डेटा साझा करने के बजाय एक सेवा का उपयोग करें (मेरा जवाब देखें)। –

उत्तर

2

$ प्रसारण विधि पर एक नज़र डालें।

सभी बच्चे स्कोप (और उनके बच्चों) के लिए नीचे की ओर एक घटना नाम डिस्पैच पंजीकृत एनजी को अधिसूचित $ rootScope श्रोताओं पर # $ $।

+0

धन्यवाद ब्रूनो। लेकिन मैं कुछ और ढूंढ रहा था, क्योंकि "मूल्य" पर देखते हुए प्रत्येक क्रिया को "मूल्य" से असंबंधित किया जाता है ताकि यह जांच सके कि "मूल्य" बदल गया है, क्योंकि प्रत्येक पाचन चक्र के हिस्से के रूप में घड़ी चर सत्यापित किए जाते हैं। –

+0

क्या '$ rootcope' से अधिक सेवा चुनने का कोई विशेष कारण है? –

5

आप सीधे बाल नियंत्रक में स्ट्रिंग मान का संदर्भ नहीं दे सकते हैं। प्रोटोटाइप विरासत की वजह से value बच्चे के दायरे पर स्थापित होता है (जो कि जब आप बच्चे नियंत्रक का उपयोग करते हैं तो बनाया जाता है) उस संपत्ति को मूल दायरे की संपत्ति को अपडेट करने के बजाय बच्चे के दायरे पर बनाता है।

आपका दायरा मॉडल नहीं है और इसलिए हमें $scope परिवर्तनीय को कई गुणों के साथ प्रदूषित करने से बचना चाहिए। एक मॉडल ऑब्जेक्ट बनाएं और उस पर उप गुण बनाएं। इस वस्तु को तब बच्चे नियंत्रकों \ स्कोप के साथ पारित किया जा सकता है।

मैंने उपरोक्त बिंदु को समझाने के लिए आपके jsfiddle को संशोधित किया।

प्रोटोटाइप विरासत के उपद्रव को समझने के लिए, मैं आपको इस wiki page के माध्यम से जाने की सलाह देता हूं।

+2

+1, लेकिन मैं स्कोप विरासत प्रदान करने के लिए एक निश्चित HTML संरचना पर निर्भर होने के बजाय नियंत्रकों के बीच डेटा साझा करने के लिए एक सेवा का उपयोग करने की सलाह देता हूं (मेरा उत्तर देखें)। –

49

जब एकाधिक नियंत्रकों को एक ही डेटा तक पहुंच की आवश्यकता होती है, तो service का उपयोग किया जाना चाहिए। आपको स्कोप विरासत पर भरोसा नहीं करना चाहिए, क्योंकि यह प्रतिबंधित करता है कि आप अपना HTML कैसे लिख सकते हैं। उदाहरण के लिए, आपने भविष्य में निर्णय लिया है कि DerivedController बेसकंट्रोलर का बच्चा नहीं होना चाहिए।

आपकी सेवा आम तौर पर एक सार्वजनिक एपीआई प्रदान करनी चाहिए, और कार्यान्वयन को छुपाएं। इससे आंतरिक को पुन: सक्रिय करना आसान हो जाता है।

HTML:

<div ng-controller="BaseController"> 
    <p>Base Controller Value: {{model.getValue()}}</p> 
    <button ng-click="model.updateValue('Value updated from Base')">Update In Base</button> 
    <div ng-controller="DerivedController"> 
     <p>Derived Controller Value: {{model.getValue()}}</p> 
     <button ng-click="model.updateValue('Value updated from Derived')">Update In Derived</button> 
    </div> 
</div> 

जावास्क्रिप्ट:

app.factory('sharedModel', function() { 
    // private stuff 
    var model = { 
     value: "initial Value" 
    }; 
    // public API 
    return { 
     getValue: function() { 
      return model.value; 
     }, 
     updateValue: function(value) { 
      model.value = value; 
     } 
    }; 
}); 

function BaseController($scope, sharedModel) { 
    $scope.model = sharedModel; 
} 

function DerivedController($scope, sharedModel) { 
    $scope.model = sharedModel; 
} 

Fiddle

इसके अलावा, मैं नियंत्रकों के बीच साझा करने के लिए $ rootScope का उपयोग करने की अनुशंसा नहीं करता हूं।

+0

मैं तुम्हारा बिंदु देखता हूं, लेकिन यह विधि बहुत वर्बोज़ लगती है। क्या हम अद्यतन विधि का उपयोग किए बिना सेवा द्वारा लौटाए गए मॉडल में अपडेट नहीं कर सकते हैं? – Chandermani

+1

सिर्फ यह कहने के लिए कि आपने मुझे बचाया :) –

+0

@ कंधर्मनी: मैं मानता हूं, मुझे लगता है कि यहां एक सेवा का उपयोग करना सुरुचिपूर्ण है। नियंत्रक विरासत को इस तरह से करने के तरीके के लिए इस उत्तर पर एक नज़र डालें जो HTML संरचना पर निर्भर नहीं है: http://stackoverflow.com/a/20230720/62571 – cdmckay

8

आपके बेड़े में बाध्यकारी सीधे दायरे में एक संपत्ति पर है। आपको जिस विरासत की आवश्यकता है वह किसी ऑब्जेक्ट पर डेटा को बाध्यकारी करके प्राप्त किया जा सकता है।

http://jsfiddle.net/2Dtyq/

scope.shared = {}  
scope.shared.value = "Something" 
के बजाय सिर्फ

scope.value= "Something" 

क्या हो रहा है

?
जबकि DerivedController का निर्माण किया गया है, प्रोटोकॉपी में पारित होने का दायरा बेसकंट्रोलर के दायरे से प्राप्त होता है।
व्युत्पन्न नियंत्रक के दायरे की वस्तु में अभी भी "मूल्य" नामक अपनी संपत्ति नहीं है। इसलिए यह अभी भी उस संपत्ति से जुड़ा हुआ है जो इसे माता-पिता के दायरे से मिला है।
अब यदि आप पर बेस बटन में अपडेट करते हैं, तो यह दोनों बाइंडिंग में प्रतिबिंबित होगा। जिस पल पर आप पर क्लिक करते हैं, व्युत्पन्न बटन में अपडेट करें, "मूल्य" नामक एक नई संपत्ति DerviedController के दायरे पर बनाई गई है। इसलिए माता-पिता की मूल्य संपत्ति के लिए बाध्यकारी टूटा हुआ है। पर कोई और क्लिक बेस में अद्यतन दूसरे डेटा बाध्यकारी को रीफ्रेश नहीं करता है।
इसे एक अलग वस्तु में डालने से एक नई संपत्ति बनने से रोकती है ताकि विरासत अभी भी बनाए रखा जा सके।

+0

यह और @ चंदमानी का जवाब सही उत्तर हैं। यहां प्रस्तुत अन्य समाधान कामकाज हैं लेकिन व्यवहार के मूल कारण की पहचान नहीं करते हैं। – do0g

0

आदिम मूल्य का उपयोग करने के बजाय वस्तुओं का उपयोग करें। आपके मामले में इस तरह की एक वस्तु को परिभाषित करें

$scope.obj = {"value":"base"}; 

और कोशिश करें (obj.value)। यह काम करेगा।

+0

क्या आपका मतलब $ scope.obj = {"value": "base"} था; कारण आपके लिए वैध जेएस की तरह प्रतीत नहीं होता है। –

+0

@ halkeye हाँ क्षमा करें। उसे बदल दिया। धन्यवाद !!! –

0

ऐसा इसलिए होता है क्योंकि ngController एक नया $ स्कोप बनाता है और मान का संदर्भ समान नहीं है। आप हल कर सकते हैं कि ऐसा $parent संपत्ति का उपयोग कर कि:

<div ng-controller="BaseController"> 
    <p>Base Controller Value: {{value}}</p> 
    <div ng-controller="DerivedController"> 
     <p>Derived Controller Value: {{$parent.value}}</p> 
    </div> 
</div> 

और DerivedController में आप ऐसा ही कुछ का उपयोग कर सकते हैं: $scope.$parent.value

लेकिन लागू करने के लिए यह controllerAs सिंटैक्स का उपयोग करने के लिए है कि सबसे अच्छा तरीका है।

<div ng-controller="BaseController as BaseController "> 
<p>Base Controller Value: {{BaseController.value}}</p> 
<div ng-controller="DerivedController"> 
    <p>Derived Controller Value: {{BaseController.value}}</p> 
</div> 

और DerivedController में आप ऐसा ही कुछ का उपयोग कर सकते हैं: $scope.BaseController.value

कि कोड अधिक पठनीयता के लिए देते हैं, क्योंकि आप जानते हैं नियंत्रक आप संदर्भित कर रहे है क्या।कि ngController Docs या Digging into Angular’s “Controller as” syntax by ToddMotto

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