2013-02-19 48 views
11

मैं एक छोटे से बेला तैयार किया और कम से कम करने के लिए इसे नीचे उबला हुआ:कोणीय बूटस्ट्रैप (टैब): डेटा बाइंडिंग का काम करता है केवल एक तरह से

http://jsfiddle.net/lpeterse/NdhjD/4/

<script type="text/javascript"> 
    angular.module('app', ['ui.bootstrap']); 

    function Ctrl($scope) { 
     $scope.foo = "42"; 
} 
</script> 


<div ng-app="app" ng-controller="Ctrl"> 
    1: {{foo}}<br /> 
    2: <input ng-model="foo" /> 
    <tabs> 
     <pane heading="tab"> 
      3: {{foo}}<br /> 
      4: <input ng-model="foo" /> 
     </pane> 
    </tabs>  
</div> 

शुरुआत में सभी दृश्यों को संदर्भित मॉडल Ctrl.foo

यदि आप 2: इनपुट में कुछ बदलते हैं तो यह मॉडल को सही तरीके से अपडेट करता है और यह परिवर्तन सभी विचारों के लिए प्रचारित हो जाता है।

इनपुट 4: में कुछ बदलना केवल उसी फलक में शामिल विचारों को प्रभावित करता है। यह किसी भी तरह से फोर्क के दायरे की तरह व्यवहार करता है। बाद में 2: से परिवर्तन टैब में अब दिखाई नहीं देते हैं।

मैंने निर्देश, स्कॉप्स और ट्रांसक्यूशन पर कोणीय दस्तावेज़ पढ़े, लेकिन इस अवांछित व्यवहार के लिए स्पष्टीकरण नहीं मिला।

मैं किसी भी संकेत के लिए आभारी होंगे :-)

+0

जेएसफ़िल्ड वर्तमान में नीचे है। आपको किसी भी तरह से प्रश्न में प्रासंगिक कोड शामिल करना चाहिए। –

उत्तर

12

समस्या के समान ही है जब आप एक आदिम संपादित - <pane> निर्देश एक नया गुंजाइश जो माता-पिता से विरासत पैदा करता है।

अब, जावास्क्रिप्ट विरासत <pane> निर्देश का काम करने के तरीके के अनुसार foo स्ट्रिंग आदिम की अपनी प्रतिलिपि है, और जब आप इसे संपादित करते हैं तो आप इसे केवल फलक बाल दायरे पर संपादित कर रहे हैं।

एक सरल समाधान अपने माता पिता पर किसी वस्तु में foo डाल करने के लिए किया जाएगा Ctrl:

function Ctrl($scope) { 
    $scope.data = { foo: 42 }; 
} 

तो फिर आप अपने HTML में ऐसा कर सकते हैं:

<tabs><pane><input ng-model="data.foo"></pane></tabs> 

क्यों यह एक वस्तु के साथ काम करता ? क्योंकि जब <pane> माता-पिता के दायरे को विरासत में लेता है, तो data का संदर्भ उसी ऑब्जेक्ट को माता-पिता Ctrl के रूप में स्मृति में संदर्भित करेगा। स्ट्रिंग्स और संख्याओं जैसे प्राइमेटिव्स को विरासत में कॉपी किया जाता है, और ऑब्जेक्ट्स एक ही ऑब्जेक्ट में बस एक नया पॉइंटर बनाते हैं।

टी एल; डॉ: <pane> नया गुंजाइश foo स्ट्रिंग foo की एक नई प्रतिलिपि जो जब संपादित माता-पिता के लिए Ctrl पर नहीं बदलेगा के रूप में आदिम इनहेरिट करती है। <pane> का नया दायरा उसी ऑब्जेक्ट के संदर्भ के रूप में data जैसी ऑब्जेक्ट का उत्तराधिकारी होगा, और <pane> स्कोप पर संपादित होने पर उसी ऑब्जेक्ट को मूल दायरे पर संदर्भित किया जाएगा।

सहायक लेख: https://github.com/angular/angular.js/wiki/The-Nuances-of-Scope-Prototypal-Inheritance

+0

ठीक है, जैसा कि आप समझाते हैं कि यह समझ में आता है। मुझे उम्मीद नहीं थी कि एक नया दायरा सचमुच तत्वों को उस दायरे से प्रतिलिपि बनाता है जो प्राप्त होता है, जिससे निश्चित रूप से प्राइमेटिव के लिए इस व्यवहार की ओर जाता है। फिर भी, बहुत भ्रमित है कि उस नए दायरे को पहले लिखने पर बनाया गया है। इससे पहले विचार अभी भी मूल दायरे को प्रतिबिंबित करते हैं। टीएल; डॉ: प्राइमेटिव्स का उपयोग न करें :-) –

+0

@ लार्स, प्राथमिकताएं कॉपी नहीं की जाती हैं जब बच्चे का दायरा बनाया जाता है। माता-पिता के दायरे आदिम मूल्यों को बच्चे के दायरे में "प्रतिलिपि" कब प्राप्त किया जाता है, इस बारे में थोड़ा और स्पष्टीकरण के लिए मेरा उत्तर देखें। –

+0

यह मेरे लिए इसे हल किया गया! –

0

समस्या टैब निर्देश में निहित है। मुझे लगता है कि line 1044 of ui-bootstrap-tpls-0.1.0.js पर।

यदि आप scope: {} से scope: { foo: '='} बदलते हैं तो आपको दो-तरफा डेटा बाध्यकारी देना चाहिए।

Angular Docs से

:

= या = attr - एक स्थानीय गुंजाइश संपत्ति और नाम की मूल गुंजाइश संपत्ति attr विशेषता के मान के माध्यम से परिभाषित के बीच द्वि-दिशात्मक बंधन की स्थापना की। यदि कोई attr नाम निर्दिष्ट नहीं किया गया है तो विशेषता नाम स्थानीय नाम के समान माना जाता है। स्कोप की दी गई और विजेट परिभाषा: {localModel: '= myAttr'}, फिर विजेट स्कोप प्रॉपर्टी स्थानीय मॉडल माता-पिता के माता-पिता के मूल्य को प्रतिबिंबित करेगा। ParentModel में कोई भी परिवर्तन स्थानीय मॉडल में दिखाई देगा और स्थानीय मॉडल में कोई भी परिवर्तन पेरेंट मॉडल में प्रतिबिंबित होगा। -दोहराने एनजी

4

<tabs> और <pane> निर्देशों प्रत्येक (क्योंकि वे दोनों transclude: true, है) जो prototypically माता पिता दायरे से विरासत एक नया transcluded बच्चे गुंजाइश बनाते हैं, और एक अलग बच्चा गुंजाइश जो prototypically नहीं है से विरासत माता-पिता का दायरा <input...><pane> के अंदर स्थानांतरित बच्चे के दायरे का उपयोग करता है।

जब <pane> अंदर input पहले प्रदान की गई है, यह $scope.foo के मूल्य के साथ भर जाता है। सामान्य जावास्क्रिप्ट प्रोटोटाइप विरासत यहां खेलता है ... प्रारंभ में foo स्थानांतरित बच्चे के दायरे पर परिभाषित नहीं है (प्रोटोटाइप विरासत प्राइमेटिव्स की प्रतिलिपि नहीं करता है), इसलिए जावास्क्रिप्ट प्रोटोटाइप श्रृंखला का पालन करता है और मूल ऑब्जेक्ट/$ स्कोप को देखता है, और इसे वहाँ पाता है। 42 टेक्स्टबॉक्स में डाल दिया गया है। स्थानांतरित बच्चे का दायरा प्रभावित/परिवर्तित नहीं हुआ है (अभी तक)।

यदि आप पहला टेक्स्टबॉक्स संपादित करते हैं, तो दूसरा टेक्स्टबॉक्स अपडेट किया गया है क्योंकि जावास्क्रिप्ट अभी भी $scope.foo के मान को खोजने के लिए प्रोटोटाइप विरासत का उपयोग कर रहा है।

यदि आप 429 कहने के लिए दूसरा टेक्स्टबॉक्स संपादित करते हैं, तो कोणीय $scope.foo पर मान लिखता है, लेकिन ध्यान दें कि $ गुंजाइश स्थानांतरित बच्चे का दायरा है। चूंकि foo एक आदिम है, यह उस बच्चे के दायरे पर एक नई संपत्ति बनाता है - इस प्रकार जावास्क्रिप्ट बेहतर या बदतर के लिए काम करता है। यह नई संपत्ति उसी नाम की मूल दायरे की संपत्ति को छाया/छुपाएगी। प्रोटोटाइप विरासत यहां खेल नहीं है। (लेख एंडी ने अपनी पोस्ट में उल्लेख किया है (जो on SO भी है) चित्रों के साथ विस्तार से यह भी बताता है।) क्योंकि बच्चे के दायरे में अब foo संपत्ति है, अब यह उस स्थानीय संपत्ति को पढ़ने और लिखने के लिए उपयोग करेगी, इसलिए ऐसा प्रतीत होता है अभिभावक दायरे से "डिस्कनेक्ट"।

किसी ऑब्जेक्ट (आदिम के बजाए) का उपयोग समस्या को हल करता है क्योंकि प्रोटोटाइप विरासत हमेशा खेल में होती है। स्थानांतरित बच्चे के दायरे को मूल दायरे में वस्तु का संदर्भ मिलता है। data.foo पर लिखने के लिए माता-पिता पर data ऑब्जेक्ट को लिखा गया है, न कि स्थानांतरित बच्चे के दायरे।