2013-04-18 7 views
6

मैं एक तत्व में 2 टेम्पलेट्स इंजेक्षन और उन पर संचालित करने के लिए कोशिश कर रहा हूँ:AngularJS: एक ही तत्व पर ट्रांसक्लुजन के साथ कई निर्देशों

<div 
    ic-first="foo" 
    ic-second="bar" 
    ic-third="baz" 
    ic-fourth="qux" 
> 
</div> 

icFirst के एक बच्चे के रूप में एक खाली div टेम्प्लेट के माध्यम से इंजेक्षन चाहिए इसका तत्व icSecond अपने तत्व के दूसरे बच्चे के रूप में (सामग्री के एक समूह के साथ) एक दूसरे div इंजेक्षन चाहिए, ताकि परिणामस्वरूप एचटीएमएल दिखाई देगा:

<div 
    ic-first="foo" // priority: 100 
    ic-second="bar" // priority: 50 
    ic-third="baz" // priority: 0 
    ic-fourth="qux" // priority: 0 
> 
    <div id="foo"></div> 
    <div> <!-- a bunch of stuff from the templateUrl --> </div> 
</div> 

दोनों icFirst और icSecond इंजेक्षन जाएगा अन्य तत्वों नव निर्मित कंटेनरों में।

जब मैं दोनों के निर्देशों पर एक निर्देश टेम्पलेट संपत्ति निर्दिष्ट करते हैं, मैं कोई त्रुटि मिलती है: जब मैं दोनों निर्देशों को transclude: true जोड़ने

Error: Multiple directives [icFirst, icSecond] asking for template on: <div ic-first

, icFirst ठीक निष्पादित करता है ... लेकिन फिर उसी पर अन्य निर्देशों तत्व निष्पादित नहीं किया जाता है। जब मैं transclude: 'element' सेट करता हूं, तो अन्य निर्देश निष्पादित करते हैं लेकिन मुझे एक त्रुटि मिलती है कि पहला बच्चा ($scope.firstObj) अपरिभाषित है।

सभी चार निर्देशों एक दूसरे की गुंजाइश के लिए उपयोग की जरूरत है, तो मैं अपने अधिकतर कार्य कर रहा हूँ अपने नियंत्रकों में:

app.directive('icFirst', ['ic.config', function (icConfig) { 
    return { 
    restrict: 'A', 
    priority: 100, 
    template: '<div id="{{firstId}}"></div>', 
    replace: false, 
    transclude: 'element', 
    controller: function icFirst($scope, $element, $attrs) { 
     // … 
     $scope.firstId = $scope.opts.fooId; 
     $scope.firstElm = $element.children()[0]; 
     $scope.firstObj = {}; // this is used by the other 3 directives 
    }, 
    link: function(scope, elm, attrs) { … } // <- event binding 
    } 
); 
app.directive('icSecond', ['ic.config', function (icConfig) { 
    return { 
    restrict: 'A', 
    priority: 0, 
    templateUrl: 'views/foo.html', 
    replace: false, 
    transclude: 'element', 
    controller: function icSecond($scope, $element, $attrs) { 
     // … 
     $scope.secondElm = $element.children()[1]; 
     $scope.secondObj = new Bar($scope.firstObj); 
     //^is used by the remaining 2 directives & requires obj from icFirst 
    }, 
    link: function(scope, elm, attrs) { … } // <- event binding 
    } 
); 

नोट मैं प्रलेखित व्यवहार से मेल करने के replace: false के व्यवहार को सही है, जैसा पुल अनुरोध #2433 में वर्णित है।

मैंने नियंत्रक में $scope.firstObj को तुरंत चालू करने की कोशिश की, और इसे लिंकएफएन में स्थापित करने की उम्मीद की (उम्मीद है कि रूपांतरण निष्पादन के समय तक पूरा हो जाएगा), लेकिन मुझे एक ही समस्या मिलती है। ऐसा लगता है कि पहला बच्चा वास्तव में एक टिप्पणी है।

उत्तर

1

एकमात्र कारण मैं ऊपर आ सकता है कि के साथ इस त्रुटि फेंक बताते हैं कि AngularJS टीम अनावश्यक अधिलेखित कर से बचने के लिए कोशिश कर रहा था है/डोम हेरफेर:

replace: false बनाम प्रलेखित व्यवहार के वास्तविक व्यवहार को देखते हुए, मुझे लगता है कि वास्तविक वास्तव में इरादा व्यवहार है। यदि यह सत्य है, तो एक ही तत्व पर एकाधिक टेम्पलेट्स/टेम्पलेट यूआरएल का उपयोग करने की इजाजत देने के बाद के बाद वाले टेम्पलेट्स को पिछले ओवरराइट करने का कारण बन जाएगा।

के बाद से मैं पहले से ही स्रोत संशोधित, दस्तावेज व्यवहार मैच के लिए त्वरित सुधार के रूप में, मैं फिर से (/src/ng/compile.js:700) स्रोत संशोधित assertNoDuplicate जांच (जो angular.js:4624 से मेल खाती है) को हटाने के लिए। अब मैं निम्नलिखित 2 वस्तुओं लौटने के लिए, और यह काम करता है, और मैं किसी भी नकारात्मक असर नहीं मिल सकता है:

// directive icFirst 
return { 
    restrict: 'A', 
    priority: 100, 
    replace: false, 
    template: '<div id="{{firstId}}"></div>', 
    require: ["icFirst"], 
    controller: Controller, 
    link: postLink 
}; 
// directive icSecond 
return { 
    restrict: 'A', 
    require: ['icFirst'], 
    replace: false, 
    templateUrl: 'views/bar.html', 
    priority: 50, 
    controller: Controller, 
    link: postLink 
}; 

† तो स्थायी बनाया, चेक शायद होना चाहिए
if (directive.templateUrl && directive.replace)
(और के लिए समान directive.template)

+2

अब एक आसान तरीका है।बस अपने निर्देश के लिए '$$ tlb: true' जोड़ें और यह जोर से बाईपास करेगा। –

+1

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

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