डोम द्वारा रेंडरिंग समाप्त करने के बाद मैं एक निर्देश कैसे चला सकता हूं?


115

मुझे कोई स्पष्ट नहीं (कोणीय जेएस डॉक्स पढ़कर) समाधान के साथ एक प्रतीत होता है सरल समस्या है ।

मुझे एक कोणीय जेएस निर्देश मिला है जो डोम में एक कंटेनर की ऊंचाई को परिभाषित करने के लिए अन्य DOM तत्वों की ऊंचाई के आधार पर कुछ गणना करता है।

ऐसा ही कुछ निर्देश के अंदर चल रहा है:

return function(scope, element, attrs) {
    $('.main').height( $('.site-header').height() -  $('.site-footer').height() );
}

मुद्दा यह है कि जब निर्देश चलता है, तो $('site-header')नहीं पाया जा सकता है, jQuery के लिपटे DOM तत्व मुझे चाहिए के बजाय एक खाली सरणी लौटा रहा है।

क्या कोई कॉलबैक है जिसे मैं अपने निर्देश के भीतर उपयोग कर सकता हूं जो केवल DOM लोड होने के बाद चलता है और मैं सामान्य DOM jQuery चयनकर्ता शैली प्रश्नों के माध्यम से अन्य DOM तत्वों को एक्सेस कर सकता हूं?


1
आप कस्टम ईवेंट का उपयोग करने के लिए स्कोप। $ On () और स्कोप। $ Emit () का उपयोग कर सकते हैं। यह सुनिश्चित नहीं है कि यह सही / अनुशंसित दृष्टिकोण है या नहीं।
तोश

जवाबों:


137

यह इस बात पर निर्भर करता है कि आपके $ ('साइट-हेडर') का निर्माण कैसे किया जाता है।

आप 0 विलंब से $ टाइमआउट का उपयोग करने का प्रयास कर सकते हैं । कुछ इस तरह:

return function(scope, element, attrs) {
    $timeout(function(){
        $('.main').height( $('.site-header').height() -  $('.site-footer').height() );
    });        
}

स्पष्टीकरण यह कैसे काम करता है: एक , दो

$timeoutअपने निर्देश में इंजेक्शन लगाना न भूलें :

.directive('sticky', function($timeout)

5
धन्यवाद, मैंने इसे युगों तक काम करने की कोशिश की जब तक मुझे एहसास नहीं हुआ कि मैं $timeoutनिर्देशन में पारित नहीं हुआ हूं । रवींद्र। सब कुछ अब काम करता है, चीयर्स।
जनीस

5
हां, आपको $timeoutइस तरह निर्देशन करने की आवश्यकता है :.directive('sticky', function($timeout) { return function (scope, element, attrs, controller) { $timeout(function(){ }); }); };
व्लादिमीर स्टार्कोव

19
आपकी लिंक की गई व्याख्याएँ बताती हैं कि टाइमआउट ट्रिक जावास्क्रिप्ट में क्यों काम करती है, लेकिन AngularJS के संदर्भ में नहीं। से आधिकारिक दस्तावेज : " [...] 4. $ evalAsync कतार अनुसूची काम जो वर्तमान ढेर फ्रेम के बाहर पाए जाते हैं की जरूरत के लिए प्रयोग किया जाता है, लेकिन ब्राउज़र की दृष्टि से पहले प्रस्तुत करना। यह आमतौर पर setTimeout (0) के साथ किया जाता है, लेकिन सेटटाइमआउट (0) दृष्टिकोण धीमेपन से ग्रस्त है और देखने में चंचलता का कारण हो सकता है क्योंकि ब्राउज़र प्रत्येक घटना के बाद दृश्य प्रदान करता है। [...] "(जोर मेरा)
अल्बर्टो

12
मैं एक ऐसी ही समस्या का सामना कर रहा हूं और मैंने पाया है कि मुझे अपने निर्देश को निष्पादित करने से पहले DOM को लोड करने की अनुमति देने के लिए लगभग 300ms की आवश्यकता है। मैं वास्तव में इस तरह प्रतीत होता है कि मनमाने ढंग से संख्या में खामियों को दूर करना पसंद नहीं करता। मुझे यकीन है कि DOM लोडिंग की गति उपयोगकर्ता के आधार पर अलग-अलग होगी। तो मैं कैसे सुनिश्चित कर सकता हूं कि मेरे ऐप का उपयोग करने वाले किसी व्यक्ति के लिए 300ms काम करेंगे?
रखने के लिए

5
इस उत्तर के बारे में बहुत खुश नहीं हैं .. जबकि यह ओपी के प्रश्न का उत्तर देता प्रतीत होता है .. यह उनके मामले के लिए बहुत विशिष्ट है और यह समस्या के अधिक सामान्य रूप के लिए प्रासंगिक है (यानी डोम के लोड होने के बाद निर्देश चलाना) स्पष्ट नहीं है + यह अभी भी hacky है .. सब पर इसके बारे में कोणीय विशिष्ट में कुछ भी नहीं
abbood

44

यहाँ है मैं इसे कैसे करते हैं:

app.directive('example', function() {

    return function(scope, element, attrs) {
        angular.element(document).ready(function() {
                //MANIPULATE THE DOM
        });
    };

});

1
यहां तक ​​कि angular.element की भी आवश्यकता नहीं होनी चाहिए क्योंकि तत्व पहले से ही उपलब्ध है:element.ready(function(){
timhc22

1
@ timhc22 तत्व निर्देश के ट्रिगर होने वाले DOMElement का संदर्भ है, आपकी अनुशंसा पृष्ठ दस्तावेज़ ऑब्जेक्ट के लिए एक DOMElement संदर्भ में परिणाम नहीं करेगा।
तोबियस

यह ठीक से काम नहीं करता है। मैं इस दृष्टिकोण के माध्यम से ऑफसेटविट = 0 प्राप्त कर रहा हूं
एलेक्सी श।

37

संभवतः लेखक को अब मेरे उत्तर की आवश्यकता नहीं होगी। फिर भी, पूर्णता के लिए मुझे लगता है कि अन्य उपयोगकर्ता इसे उपयोगी पा सकते हैं। सबसे अच्छा और सबसे सरल समाधान $(window).load()लौटे फ़ंक्शन के शरीर के अंदर उपयोग करना है। (वैकल्पिक रूप से आप उपयोग कर सकते हैंdocument.ready । यह वास्तव में निर्भर करता है कि आपको सभी छवियों की आवश्यकता है या नहीं)।

का उपयोग करते हुए $timeoutमेरी विनम्र राय का एक बहुत ही कमजोर विकल्प है और कुछ मामलों में विफल हो सकता है।

यहाँ मैं पूरा कोड का उपयोग करेगा:

.directive('directiveExample', function(){
   return {
       restrict: 'A',
       link: function($scope, $elem, attrs){

           $(window).load(function() {
               //...JS here...
           });
       }
   }
});

1
क्या आप विस्तृत कर सकते हैं कि यह "कुछ मामलों में विफल क्यों हो सकता है"? आपके लिए क्या मायने हैं?
15:24

6
आप मान रहे हैं कि jQuery यहां उपलब्ध है।
जोनाथन क्रेमिन

3
@JonathanCremin jQuery का चयन ओपी के अनुसार मुद्दा है
निक देवरेको

1
यह बहुत अच्छा काम करता है, लेकिन अगर कोई पोस्ट है जो निर्देश के साथ नई वस्तुओं का निर्माण करता है तो प्रारंभिक भार के बाद विंडो लोड नहीं होगा और इसलिए यह सही ढंग से काम नहीं करेगा।
ब्रायन स्कॉट

@BrianScott - मैंने प्रारंभिक पेज रेंडरिंग के लिए $ (विंडो) .load का संयोजन इस्तेमाल किया (मेरा उपयोग-केस एम्बेडेड फॉन्ट फ़ाइलों का इंतजार कर रहा था) और फिर एलिमेंटिंग। पहले से ही स्विचिंग विचारों का ध्यान रखना।
आआआआआआआआ

8

एक ngcontentloadedघटना है, मुझे लगता है कि आप इसका उपयोग कर सकते हैं

.directive('directiveExample', function(){
   return {
       restrict: 'A',
       link: function(scope, elem, attrs){

                $$window = $ $window


                init = function(){
                    contentHeight = elem.outerHeight()
                    //do the things
                }

                $$window.on('ngcontentloaded',init)

       }
   }
});

21
क्या आप बता सकते हैं कि क्या $ $windowकर रहा है?
कैटफ़िश

2
कुछ कॉफ़ीस्क्रिप्ट की तरह दिखता है, शायद यह $ ($ विंडो) और $ विंडो को निर्देश में इंजेक्ट किया जा रहा था
mdob

5

यदि आप बाह्य संसाधनों के कारण $ टाइमआउट का उपयोग नहीं कर सकते हैं और समय के साथ विशिष्ट मुद्दे के कारण एक निर्देश का उपयोग नहीं कर सकते, तो प्रसारण का उपयोग करें।

$scope.$broadcast("variable_name_here");वांछित बाहरी संसाधन या लंबे समय तक चलने वाले नियंत्रक / निर्देश के पूरा होने के बाद जोड़ें ।

अपने बाहरी संसाधन लोड होने के बाद फिर नीचे जोड़ें।

$scope.$on("variable_name_here", function(){ 
   // DOM manipulation here
   jQuery('selector').height(); 
}

उदाहरण के लिए एक आस्थगित HTTP अनुरोध के वादे में।

MyHttpService.then(function(data){
   $scope.MyHttpReturnedImage = data.image;
   $scope.$broadcast("imageLoaded");
});

$scope.$on("imageLoaded", function(){ 
   jQuery('img').height(80).width(80); 
}

2
यह समस्या को हल करने के लिए नहीं जा रहा है, क्योंकि लोड किए गए डेटा का मतलब यह नहीं है, कि वे पहले से ही डोम में प्रदान किए गए हैं, भले ही वे डोम तत्वों से जुड़े उचित दायरे के चर में हों। पल भर में वे दायरे में लोड हो जाते हैं और डोम में प्रदान किए गए आउटपुट के बीच एक समय-सीमा होती है।
रेने स्टैलर

1

मुझे इसी तरह की समस्या थी और मैं यहां अपना समाधान साझा करना चाहता हूं।

मेरे पास निम्न HTML है:

<div data-my-directive>
  <div id='sub' ng-include='includedFile.htm'></div>
</div>

समस्या: पैरेंट डिव के निर्देशन के लिंक-फंक्शन में मैं चाइल्ड डिव # सब को jquery'ing करना चाहता था। लेकिन इसने मुझे सिर्फ एक खाली वस्तु दी क्योंकि निर्देशन का लिंक फ़ंक्शन चलने पर एनजी-इन समाप्त नहीं हुआ था। इसलिए पहले मैंने $ टाइमआउट के साथ एक गंदा काम किया, जिसने काम किया लेकिन क्लाइंट-गति पर निर्भर देरी-पैरामीटर (किसी को भी पसंद नहीं है)।

काम करता है लेकिन गंदा:

app.directive('myDirective', [function () {
    var directive = {};
    directive.link = function (scope, element, attrs) {
        $timeout(function() {
            //very dirty cause of client-depending varying delay time 
            $('#sub').css(/*whatever*/);
        }, 350);
    };
    return directive;
}]);

यहाँ साफ समाधान है:

app.directive('myDirective', [function () {
    var directive = {};
    directive.link = function (scope, element, attrs) {
        scope.$on('$includeContentLoaded', function() {
            //just happens in the moment when ng-included finished
            $('#sub').css(/*whatever*/);
        };
    };
    return directive;
}]);

शायद यह किसी की मदद करे।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.