2015-09-15 19 views
6

के भीतर नियंत्रक को स्थानांतरित करते समय तत्व/स्कोप स्थिति बनाए रखें एक कोणीय अनुप्रयोग में, मैं एक तत्व को डीओएम पेड़ के एक हिस्से से दूसरे भाग में स्थानांतरित करना चाहता हूं, बिना किसी तत्व के नियंत्रक/एस को पुनः लोड किए बिना।डीओएम

मैं एक सरल plunker बनाया है वर्णन करने के लिए: http://plnkr.co/edit/sqBRM3ZQ5G9xpiNd1MXm?p=preview

इस plunker में, केवल डेटा बनाए रखे जाने की Toggler राज्य है, लेकिन वास्तविकता में यह डेटा की एक बहुत बड़ी राशि है, जो एक आवश्यकता हो सकती है हो सकता है शुरू करने के लिए बहुत सारे प्रयास।

मैं क्या करना चाहता हूं कि डायरेक्टिव 1 से निर्देश 1 में टेम्पलेट 1 को स्थानांतरित करने में सक्षम होना है, लेकिन मैं टॉगलर की स्थिति को बनाए रखना चाहता हूं। इस परिदृश्य में, यदि आप इसे हरा बनाने के लिए टॉगलर पर क्लिक करते हैं, और "सूची 1 से 2 में स्थानांतरित करें" पर क्लिक करें, तो यह इसे निर्देश 2 पर ले जायेगा लेकिन रंग को लाल रंग में रीसेट कर देगा।

इसे रोकने के लिए, मैं केवल कोणीय को सूचित किए बिना तत्व को स्थानांतरित कर सकता हूं, लेकिन यह स्पष्ट रूप से एक टूटी हुई एप्लिकेशन स्थिति बनाता है।

मैं सिर्फ नए गुंजाइश के लिए पुराने दायरे से नियंत्रक जाने के बारे में सोचा था, लेकिन मुझे लगता है कि इस बंद के समस्याओं के कारण के रूप में पुराने नियंत्रक वर्ष तत्व डोम आदि में नहीं रह गया है जो संदर्भित किया जा सकता है

क्या इस समस्या को हल करने का कोई अच्छा तरीका है?

कुछ कोड जोड़ने क्योंकि StackOverflow ऐसा करना आवश्यक हो, लेकिन इसके बजाय plunker का संदर्भ लें: दृश्य के साथ

angular.module('app').controller('bodyController', ['$element', function ($element) { 

    this.contents1 = [{ 
     path: 'template1.html' 
    }, { 
     path: 'template2.html' 
    }]; 

    this.contents2 = [{ 
     path: 'template3.html' 
    }, { 
     path: 'template4.html' 
    }]; 

    this.move12 = function() { 
     this.contents2.push(this.contents1.pop()); 
    }; 

    this.move21 = function() { 
     this.contents1.push(this.contents2.pop()); 
    }; 

    this.naiveMove12 = function() { 
     var $elem = $($element); 
     $elem.find('container-list:eq(0) > div').last() 
      .appendTo($elem.find('container-list').eq(1)); 
    }; 

    this.naiveMove21 = function() { 
     var $elem = $($element); 
     $elem.find('container-list:eq(1) > div').last() 
      .appendTo($elem.find('container-list').eq(0)); 
    }; 

    this.logScope = function() { 
     var $elem = $($element); 
     [].forEach.call($elem.find('container-list'), function (elem, idx) { 
      console.log(idx + ': ', angular.element(elem).isolateScope().containerListCtrl); 
     }); 
    }; 
}]); 
+5

सामान ले जाने के बजाय, क्या आपके पास सिर्फ एक सिंगलटन कारखाने में डेटा नहीं हो सकता है। उस फैक्ट्री का उपयोग इवेंट एग्रीगेटर के रूप में भी करें। फिर जब आप डेटा ले जाना चाहते हैं, तो आप इसे सरल से हटा दें और इसे दूसरे में लोड करें। किसी भी राज्य को घटना के साथ भेजा जा सकता है। यदि आप विभिन्न टेम्पलेट्स को लोड करना चाहते हैं तो आप '$ टेम्पलेटप्रदाता 'और' $ संकलन' का उपयोग कर सकते हैं। –

+0

डेटा कैश को $ rootScope में लोड करने के बाद, आपके पास अपने सभी नियंत्रकों में इसका उपयोग होगा। मैंने आपके प्लंकर को रूटस्कोप जोड़ने की कोशिश की, लेकिन ऐसा लगता है कि यह काम नहीं कर रहा था। यदि आप इस दृष्टिकोण में रुचि रखते हैं तो मैं आपको इसके लिए कोड दिखा सकता हूं। – jjbskir

+0

सोचें कि मैंने नीचे आपके प्रश्न का उत्तर दिया है। काम करने के समाधान के लिए plunkr देखें। यदि आपके कोई प्रश्न हैं या यदि मैंने कुछ भी गलत समझा है तो कृपया मुझे बताएं। धन्यवाद! – jbmilgrom

उत्तर

0

युग्मन आवेदन राज्य/नियंत्रक मेरे अनुभव में सबसे अच्छा अभ्यास नहीं है, लेकिन यहाँ यह करने के लिए एक तरीका है: revised plunkr

template1.html में कुछ छोटे बदलाव हैं। केवल अन्य परिवर्तन templateController.js में हैं:

angular.module('app').controller('templateController', statefulTemplateCtrl()); 

function statefulTemplateCtrl() { 
    var state = {color: 'red'}; 
    return function(){ 
    this.state = state; 

    // this.color = 'red'; 

    this.toggleColor = function() { 
     state.color = (state.color === 'red') ? 'green' : 'red'; 
    }; 
    }; 
} 

जहां समारोह अब templateController के रूप में इस्तेमाल कॉन्फ़िगर किया गया है एक state वस्तु के संदर्भ में बनाए रखने के लिए। अब यदि आप bodyCtrl.move12() का उपयोग कर टेम्पलेट को ले जाते हैं, तो आप अपने आवेदन स्थिति को तोड़ने के बिना संचित टॉगल स्थिति को रखने में सक्षम होंगे। यह काम करता है क्योंकि नियंत्रक के पास बंद होने के माध्यम से बाहरी वस्तु का संदर्भ होता है। नतीजतन, यह को पुन: स्थापित किए बिना नए डीओएम नोड पर ng-include द्वारा पुनः-तत्काल और पुनः संकलित किया जा सकता है।

शायद एक बेहतर

उपयोग सेवाओं और/या अपने आवेदन में अलग डोम नोड्स के बीच स्थिति साझा $scope घटनाओं एपीआई को संभालने के लिए रास्ता।

<div ng-class="{ red: (tc.color === 'red'), green: (tc.color === 'green') }" ng-click="tc.toggleColor()">Toggler</div> 

और तुम में, tc वस्तु है, जो अपने टॉगल से संबंधित राज्य के सभी घरों को स्थानांतरित करने के लिए एक और नोड के लिए करना चाहते हैं:

आप टेम्पलेट, वही अपने plunker में शुरू की गई है कहो डोम, आप कर सकते हैं:

  • एक घटना $scope.$broadcast('nameOfEvent', tc) साथ गुंजाइश पदानुक्रम नीचे प्रेषण यदि गंतव्य नोड स्रोत के वंशज है $scope
  • $rootScope और $rootScope.$broadcast('nameOfEvent', tc) इंजेक्शन लगाने के द्वारा ऊपर गुंजाइश पदानुक्रम अगर $scope.$emit('nameOfEvent', tc) गंतव्य नोड स्रोत $scope
  • अपने अनुप्रयोग में सभी नोड्स के लिए एक घटना प्रेषण के एक पूर्वज है अगर एक घटना प्रेषण यदि गंतव्य नोड या तो किया जा सकता है ।

$ गुंजाइश घटना एपीआई के इन तरीकों में से किसी भी लागू एक नोड से दूसरे करने के लिए, आप डाटा संचारित करने के लिए, इस मामले में tc वस्तु की अनुमति देगा। गंतव्य गंतव्य नोड के साथ जुड़े नियंत्रक घटना के लिए इंतजार किया जा सकता है एक श्रोता समारोह प्रेषित डेटा प्राप्त करने में सक्षम के साथ भेज दिया:

function bindDataToController(destinationCtrl){ 
    return function(event, tc){ 
    angular.extend(destinationCtrl, tc); 
    }; 
} 

$scope.$on('nameOfEvent', bindDataToController(this)); 

प्रेषित डेटा वस्तु, tc, के साथ जुड़े नियंत्रक करने के लिए बाध्य हो जाएगी शुरू हो रहा 'nameOfEvent' के प्राप्त होने पर नया गंतव्य नोड। अब जब कि स्रोत डेटा गंतव्य नियंत्रक वस्तु के साथ विलय कर दिया गया है, ताकि स्रोत टेम्पलेट सही ढंग से गंतव्य नियंत्रक को संदर्भित कर सकते एक बार यह है, यह सुनिश्चित करें कि अपने गंतव्य नियंत्रक इस मामले 'tc' में, अपने स्रोत नियंत्रक के रूप में एक ही controllerAs नाम दिया जाता है बनाना अंत में संकलित और गंतव्य डोम नोड (जो प्रक्रिया नीचे चर्चा कर रहा है) से जुड़ी।

निकाला जा रहा है और डोम नोड्स जोड़ने कुछ हद तक तुच्छ आप उल्लेख किया है, इसलिए मैं इसे यहाँ पर चर्चा नहीं की है, लेकिन के रूप में अपने आवेदन में जोड़ सकते हैं और दूर करने के लिए आप स्रोत देखें/टेम्पलेट के लिए आसान पहुँच चाहते हैं, तो किसी भी स्थान में आवश्यक हो, आप $templateCache उपयोग कर सकते हैं।

टॉगल उदाहरण के लिए वापस, यदि आपका टॉगल देखें/स्वयं टेम्पलेट को पहले से ही एक निर्देश फ़ाइल पथ 'toggle.html' साथ templateUrl का उपयोग करता है का हिस्सा है, तो आपका खाका पहले की कुंजी 'toggle.html' के घेरे में रखा गया होगा और संग्रहीत $templateCache में ।

अपने गंतव्य नियंत्रक में, $templateCache इंजेक्षन, जो आप टेम्पलेट को पुनः प्राप्त करने की अनुमति देगा:

var template = $templateCache.get('toggle.html'); 

इंजेक्षन $ अपने गंतव्य नियंत्रक में संकलन और $ गंतव्य $ गुंजाइश (भी में इंजेक्शन के साथ टेम्पलेट संकलन गंतव्य नियंत्रक):

var $template = $compile(template)($scope); 

तो $element (यह भी गंतव्य नियंत्रक में इंजेक्शन) अपने गंतव्य नियंत्रक के साथ जुड़े करने के लिए संकलित टेम्पलेट संलग्न:

$element.append($template); 

आप केवल संकलन और प्रेषित डेटा प्राप्त होने पर संलग्न डोम को 'toggle.html' टेम्पलेट करना चाहते हैं, तो आप bindDataToController की वापसी समारोह के अंदर ऊपर अनिवार्य संकलन कोड, घटना श्रोता के रूप में पंजीकृत जगह कर सकते हैं 'nameOfEvent' के लिए। और वहां आपके पास है! ... एक डोम नोड जिसे किसी भी जटिल स्थिति के साथ "स्थानांतरित" किया गया है जिसे पहले स्रोत स्थान पर बनाया गया था।