जब AngularJS लोड हो रहा हो, तब ईवेंट भेजना


114

आश्चर्य है कि पेज लोडिंग / बूटस्ट्रैपिंग के खत्म होने का पता लगाने का सबसे अच्छा तरीका क्या है, जब सभी निर्देश संकलन / लिंकिंग करते हैं।

पहले से ही कोई घटना? क्या मुझे बूटस्ट्रैप फ़ंक्शन को ओवरलोड करना चाहिए?

जवाबों:


204

बस एक कूबड़: क्यों नहीं देखो कैसे ngCloak निर्देश यह करता है? स्पष्ट रूप से ngCloak निर्देश चीजों को लोड करने के बाद सामग्री को दिखाने का प्रबंधन करता है। मुझे यकीन है कि ngCloak को देखकर सटीक उत्तर मिलेगा ...

1 घंटे बाद संपादित करें: ठीक है, ठीक है, मैंने ngCloak को देखा और यह वास्तव में छोटा है। यह स्पष्ट रूप से तात्पर्य है कि संकलित फ़ंक्शन को {{टेम्प्लेट}} तक अभिव्यक्त नहीं किया जाएगा, जिसका मूल्यांकन किया गया है (यानी यह टेम्प्लेट लोड किया गया है), इस प्रकार ngCloak निर्देश की अच्छी कार्यक्षमता है।

मेरा शिक्षित अनुमान यह होगा कि आप बस एक ही सादगी के साथ एक निर्देश बना सकते हैं, फिर अपने संकलन कार्य में आप जो भी करना चाहते हैं। :) अपने ऐप के रूट एलिमेंट पर डायरेक्शन रखें। आप निर्देश को myOnload की तरह कह सकते हैं और इसे एक विशेषता my-onload के रूप में उपयोग कर सकते हैं। एक बार टेम्पलेट संकलित किए जाने के बाद संकलन फ़ंक्शन निष्पादित होगा (भावों का मूल्यांकन किया गया और उप-टेम्प्लेट लोड किए गए हैं)।

EDIT, 23 घंटे बाद: ठीक है, इसलिए मैंने कुछ शोध किया, और मैंने अपना प्रश्न भी पूछा । मेरे द्वारा पूछा गया प्रश्न अप्रत्यक्ष रूप से इस प्रश्न से संबंधित था, लेकिन यह संयोग से मुझे उस उत्तर की ओर ले जाता है जो इस प्रश्न को हल करता है।

इसका उत्तर यह है कि आप एक सरल निर्देश बना सकते हैं और अपने कोड को निर्देश के लिंक फ़ंक्शन में डाल सकते हैं, जो (नीचे उपयोग किए गए अधिकांश मामलों के लिए) आपके तत्व के तैयार / लोड होने पर चलेगा। आदेश के जोश के विवरण के आधार पर संकलन और लिंक फ़ंक्शन निष्पादित किए जाते हैं ,

यदि आपके पास यह मार्कअप है:

<div directive1>
  <div directive2>
    <!-- ... -->
  </div>
</div>

तो AngularJS एक निश्चित क्रम में निर्देश कार्यों को चलाकर निर्देशकों का निर्माण करेगा:

directive1: compile
  directive2: compile
directive1: controller
directive1: pre-link
  directive2: controller
  directive2: pre-link
  directive2: post-link
directive1: post-link

डिफ़ॉल्ट रूप से एक सीधा "लिंक" फ़ंक्शन एक पोस्ट-लिंक है, इसलिए आपके बाहरी डायरेक्टिव 1 का लिंक फ़ंक्शन तब तक नहीं चलेगा जब तक कि आंतरिक डाइरेक्टिव 2 के लिंक फ़ंक्शन के चलने के बाद। इसलिए हम कहते हैं कि पोस्ट-लिंक में DOM मैनिप्युलेशन करना केवल सुरक्षित है। इसलिए मूल प्रश्न की ओर, बाहरी निर्देश के लिंक फ़ंक्शन से बच्चे के निर्देश के आंतरिक HTML तक पहुंचने का कोई मुद्दा नहीं होना चाहिए, हालांकि गतिशील रूप से सम्मिलित सामग्री को संकलित किया जाना चाहिए, जैसा कि ऊपर कहा गया है।

इससे हम यह निष्कर्ष निकाल सकते हैं कि हम सब कुछ तैयार / संकलित / लिंक / लोड होने पर अपने कोड को निष्पादित करने के लिए एक निर्देश बना सकते हैं:

    app.directive('ngElementReady', [function() {
        return {
            priority: -1000, // a low number so this directive loads after all other directives have loaded. 
            restrict: "A", // attribute only
            link: function($scope, $element, $attributes) {
                console.log(" -- Element ready!");
                // do what you want here.
            }
        };
    }]);

अब आप जो कर सकते हैं, वह ऐप के मूल तत्व पर ngElementReady निर्देश को डाल दिया है, और console.logजब यह उपयोग किया जाता है, तो आग लग जाएगी:

<body data-ng-app="MyApp" data-ng-element-ready="">
   ...
   ...
</body>

यह इत्ना आसान है! बस एक सरल निर्देशन करें और इसका उपयोग करें। ;)

आप इसे और कस्टमाइज़ कर सकते हैं, ताकि इसे जोड़कर एक एक्सप्रेशन (यानी एक फंक्शन) निष्पादित कर सकें $scope.$eval($attributes.ngElementReady);:

    app.directive('ngElementReady', [function() {
        return {
            priority: Number.MIN_SAFE_INTEGER, // execute last, after all other directives if any.
            restrict: "A",
            link: function($scope, $element, $attributes) {
                $scope.$eval($attributes.ngElementReady); // execute the expression in the attribute.
            }
        };
    }]);

तब आप इसे किसी भी तत्व पर उपयोग कर सकते हैं:

<body data-ng-app="MyApp" data-ng-controller="BodyCtrl" data-ng-element-ready="bodyIsReady()">
    ...
    <div data-ng-element-ready="divIsReady()">...<div>
</body>

बस यह सुनिश्चित करें कि आपके कार्य (जैसे bodyIsReady और divIsReady) के दायरे (नियंत्रक में) में परिभाषित किया गया है कि आपका तत्व नीचे रहता है।

कैविट्स: मैंने कहा कि यह ज्यादातर मामलों के लिए काम करेगा । NgRepeat और ngIf जैसे कुछ निर्देशों का उपयोग करते समय सावधान रहें। वे अपना दायरा बनाते हैं, और आपके निर्देश में आग नहीं लग सकती। उदाहरण के लिए यदि आप हमारे नए ngElementReady निर्देश को ऐसे तत्व पर रखते हैं जिसमें ngIf भी है, और ngIf की स्थिति झूठी का मूल्यांकन करती है, तो हमारा ngElementReady निर्देश लोड नहीं होगा। या, उदाहरण के लिए, यदि आप हमारे नए ngElementReady निर्देश को एक तत्व पर रखते हैं जिसमें एक ngInclude निर्देश भी है, तो हमारा निर्देश लोड नहीं होगा यदि ngInclude के लिए टेम्पलेट मौजूद नहीं है। आप इन सभी समस्याओं में से कुछ को एक ही तत्व पर रखने के बजाय निर्देशों को घोंसला बनाकर प्राप्त कर सकते हैं। उदाहरण के लिए, ऐसा करके:

<div data-ng-element-ready="divIsReady()">
    <div data-ng-include="non-existent-template.html"></div>
<div>

इसके अलावा:

<div data-ng-element-ready="divIsReady()" data-ng-include="non-existent-template.html"></div>

NgElementReady निर्देश बाद के उदाहरण में संकलित किया जाएगा, लेकिन यह लिंक फ़ंक्शन निष्पादित नहीं किया जाएगा। नोट: निर्देश हमेशा संकलित किए जाते हैं, लेकिन उनके लिंक फ़ंक्शंस हमेशा उपरोक्त जैसे कुछ निश्चित परिदृश्यों के आधार पर निष्पादित नहीं किए जाते हैं।

EDIT, कुछ मिनट बाद:

ओह, और पूरी तरह से सवाल का जवाब देने के लिए, आप अब $emitया $broadcastआपके इवेंट को उस ng-element-readyविशेषता या फ़ंक्शन से ले सकते हैं जिसे विशेषता में निष्पादित किया गया है। :) जैसे:

<div data-ng-element-ready="$emit('someEvent')">
    ...
<div>

संपादित करें, और भी कुछ मिनट बाद:

@ साचमोरुन का जवाब भी काम करता है, लेकिन केवल शुरुआती भार के लिए। यहां एक बहुत ही उपयोगी एसओ प्रश्न है जो लिंक कार्यों app.run, और अन्य सहित आदेश चीजों को निष्पादित करता है। इसलिए, आपके उपयोग के मामले के आधार पर, app.runअच्छा हो सकता है, लेकिन विशिष्ट तत्वों के लिए नहीं, जिस स्थिति में लिंक फ़ंक्शन बेहतर हैं।

EDIT, पांच महीने बाद, 17 अक्टूबर को 8:11 PST:

यह उन विभाजनों के साथ काम नहीं करता है जो अतुल्यकालिक रूप से लोड किए गए हैं। आपको अपने हिस्से में बहीखाता जोड़ने की आवश्यकता होगी (जैसे कि एक तरीका यह है कि जब प्रत्येक सामग्री की लोडिंग पूरी हो जाए तो उसे आंशिक रूप से ट्रैक किया जाए, फिर एक घटना का उत्सर्जन करें ताकि माता-पिता का दायरा गिन सकें कि कितने हिस्से लोड किए गए हैं और आखिरकार उसे क्या करना है? सभी भाग भर जाने के बाद)।

EDIT, 23 अक्टूबर को 10:52 बजे पीएसटी:

जब एक छवि लोड होती है तो मैंने कुछ कोड फायर करने के लिए एक सरल निर्देश बनाया:

/*
 * This img directive makes it so that if you put a loaded="" attribute on any
 * img element in your app, the expression of that attribute will be evaluated
 * after the images has finished loading. Use this to, for example, remove
 * loading animations after images have finished loading.
 */
  app.directive('img', function() {
    return {
      restrict: 'E',
      link: function($scope, $element, $attributes) {
        $element.bind('load', function() {
          if ($attributes.loaded) {
            $scope.$eval($attributes.loaded);
          }
        });
      }
    };
  });

EDIT, 24 अक्टूबर को 12:48 बजे पीएसटी:

मैंने अपने मूल ngElementReadyनिर्देश में सुधार किया और इसका नाम बदल दिया whenReady

/*
 * The whenReady directive allows you to execute the content of a when-ready
 * attribute after the element is ready (i.e. done loading all sub directives and DOM
 * content except for things that load asynchronously like partials and images).
 *
 * Execute multiple expressions by delimiting them with a semi-colon. If there
 * is more than one expression, and the last expression evaluates to true, then
 * all expressions prior will be evaluated after all text nodes in the element
 * have been interpolated (i.e. {{placeholders}} replaced with actual values). 
 *
 * Caveats: if other directives exists on the same element as this directive
 * and destroy the element thus preventing other directives from loading, using
 * this directive won't work. The optimal way to use this is to put this
 * directive on an outer element.
 */
app.directive('whenReady', ['$interpolate', function($interpolate) {
  return {
    restrict: 'A',
    priority: Number.MIN_SAFE_INTEGER, // execute last, after all other directives if any.
    link: function($scope, $element, $attributes) {
      var expressions = $attributes.whenReady.split(';');
      var waitForInterpolation = false;

      function evalExpressions(expressions) {
        expressions.forEach(function(expression) {
          $scope.$eval(expression);
        });
      }

      if ($attributes.whenReady.trim().length == 0) { return; }

      if (expressions.length > 1) {
        if ($scope.$eval(expressions.pop())) {
          waitForInterpolation = true;
        }
      }

      if (waitForInterpolation) {
        requestAnimationFrame(function checkIfInterpolated() {
          if ($element.text().indexOf($interpolate.startSymbol()) >= 0) { // if the text still has {{placeholders}}
            requestAnimationFrame(checkIfInterpolated);
          }
          else {
            evalExpressions(expressions);
          }
        });
      }
      else {
        evalExpressions(expressions);
      }
    }
  }
}]);

उदाहरण के लिए, someFunctionकिसी तत्व के लोड होने और {{placeholders}}अभी तक प्रतिस्थापित न होने के लिए इसे इस तरह से उपयोग करें :

<div when-ready="someFunction()">
  <span ng-repeat="item in items">{{item.property}}</span>
</div>

someFunctionसभी item.propertyप्लेसहोल्डर्स को प्रतिस्थापित करने से पहले कॉल किया जाएगा ।

आप चाहते हैं कि इस तरह से मूल्यांकन किया जा करने के trueलिए प्रतीक्षा करने के लिए कई अभिव्यक्तियों का मूल्यांकन करें, और अंतिम अभिव्यक्ति {{placeholders}}करें:

<div when-ready="someFunction(); anotherFunction(); true">
  <span ng-repeat="item in items">{{item.property}}</span>
</div>

someFunctionऔर बदले anotherFunctionजाने के बाद निकाल दिया जाएगा {{placeholders}}

यह केवल पहली बार काम करता है एक तत्व लोड किया जाता है, भविष्य के परिवर्तनों पर नहीं। यह वांछित के रूप में काम नहीं कर सकता है यदि $digestप्लेसहोल्डर्स को शुरू में बदलने के बाद एक रखता है (एक $ पाचन 10 बार तक हो सकता है जब तक कि डेटा बदलना बंद न हो जाए)। यह उपयोग के अधिकांश मामलों के लिए उपयुक्त होगा।

EDIT, 31 अक्टूबर शाम 7:26 बजे PST:

ठीक है, यह शायद मेरा आखिरी और अंतिम अपडेट है। यह संभवतः वहाँ से उपयोग मामलों के 99.999 के लिए काम करेगा:

/*
 * The whenReady directive allows you to execute the content of a when-ready
 * attribute after the element is ready (i.e. when it's done loading all sub directives and DOM
 * content). See: /programming/14968690/sending-event-when-angular-js-finished-loading
 *
 * Execute multiple expressions in the when-ready attribute by delimiting them
 * with a semi-colon. when-ready="doThis(); doThat()"
 *
 * Optional: If the value of a wait-for-interpolation attribute on the
 * element evaluates to true, then the expressions in when-ready will be
 * evaluated after all text nodes in the element have been interpolated (i.e.
 * {{placeholders}} have been replaced with actual values).
 *
 * Optional: Use a ready-check attribute to write an expression that
 * specifies what condition is true at any given moment in time when the
 * element is ready. The expression will be evaluated repeatedly until the
 * condition is finally true. The expression is executed with
 * requestAnimationFrame so that it fires at a moment when it is least likely
 * to block rendering of the page.
 *
 * If wait-for-interpolation and ready-check are both supplied, then the
 * when-ready expressions will fire after interpolation is done *and* after
 * the ready-check condition evaluates to true.
 *
 * Caveats: if other directives exists on the same element as this directive
 * and destroy the element thus preventing other directives from loading, using
 * this directive won't work. The optimal way to use this is to put this
 * directive on an outer element.
 */
app.directive('whenReady', ['$interpolate', function($interpolate) {
  return {
    restrict: 'A',
    priority: Number.MIN_SAFE_INTEGER, // execute last, after all other directives if any.
    link: function($scope, $element, $attributes) {
      var expressions = $attributes.whenReady.split(';');
      var waitForInterpolation = false;
      var hasReadyCheckExpression = false;

      function evalExpressions(expressions) {
        expressions.forEach(function(expression) {
          $scope.$eval(expression);
        });
      }

      if ($attributes.whenReady.trim().length === 0) { return; }

    if ($attributes.waitForInterpolation && $scope.$eval($attributes.waitForInterpolation)) {
        waitForInterpolation = true;
    }

      if ($attributes.readyCheck) {
        hasReadyCheckExpression = true;
      }

      if (waitForInterpolation || hasReadyCheckExpression) {
        requestAnimationFrame(function checkIfReady() {
          var isInterpolated = false;
          var isReadyCheckTrue = false;

          if (waitForInterpolation && $element.text().indexOf($interpolate.startSymbol()) >= 0) { // if the text still has {{placeholders}}
            isInterpolated = false;
          }
          else {
            isInterpolated = true;
          }

          if (hasReadyCheckExpression && !$scope.$eval($attributes.readyCheck)) { // if the ready check expression returns false
            isReadyCheckTrue = false;
          }
          else {
            isReadyCheckTrue = true;
          }

          if (isInterpolated && isReadyCheckTrue) { evalExpressions(expressions); }
          else { requestAnimationFrame(checkIfReady); }

        });
      }
      else {
        evalExpressions(expressions);
      }
    }
  };
}]);

इसे इस तरह इस्तेमाल करें

<div when-ready="isReady()" ready-check="checkIfReady()" wait-for-interpolation="true">
   isReady will fire when this {{placeholder}} has been evaluated
   and when checkIfReady finally returns true. checkIfReady might
   contain code like `$('.some-element').length`.
</div>

बेशक, यह शायद अनुकूलित किया जा सकता है, लेकिन मैं इसे उस पर छोड़ दूँगा। requestAnimationFrame अच्छा है।


3
वास्तव में उन सभी "डेटा-" उपसर्गों से परेशान। मुझे खुशी है कि मैं खुद उनका इस्तेमाल नहीं करता।
स्टॉल्सविक

1
@stolsvik हे, हाँ, सबसे आधुनिक ब्राउज़रों में जिनकी उन्हें आवश्यकता नहीं है।
त्रसुक्र

49
इस उत्तर में डाले गए समय और प्रयास के लिए वोट का वर्णन करता है। अच्छा काम!
गॉर्डिएड

8
अच्छा जवाब है, लेकिन कृपया सभी "एडिट" लाइनों को हटाने और अपने उत्तर को थोड़ा पुनर्गठन करने पर विचार करें। संपादित इतिहास आपके उत्तर के नीचे "संपादित ..." लिंक के माध्यम से उपलब्ध है, और यह पढ़ते समय विचलित करता है।
user247702

2
स्रोत कोड वास्तव में उपयोगी होगा। और अगर आप इसे npm पर सार्वजनिक कर सकते हैं, तो यह सही होगा। वास्तव में अच्छा जवाब, वास्तव में अच्छी तरह से समझाया, इस में डाल प्रयास के लिए +1।
tfrascaroli

38

में के लिए डॉक्सangular.Module , वहाँ एक प्रविष्टि का वर्णन है runसमारोह:

काम को पंजीकृत करने के लिए इस पद्धति का उपयोग करें जो तब किया जाना चाहिए जब इंजेक्टर सभी मॉड्यूल को लोड करने के लिए किया जाता है।

तो अगर आपके पास कुछ मॉड्यूल है जो आपका ऐप है:

var app = angular.module('app', [/* module dependencies */]);

मॉड्यूल लोड होने के बाद आप सामान चला सकते हैं:

app.run(function() {
  // Do post-load initialization stuff here
});

EDIT: बचाव के लिए मैनुअल इनिशियलाइज़ेशन

तो यह बताया गया है कि runDOM तैयार होने और लिंक अप होने पर कॉल नहीं किया जाता है। जब $injectorमॉड्यूल द्वारा संदर्भित के लिए यह कहा जाता हैng-app इसकी सभी निर्भरताएं भरी हुई हैं, जो DOM संकलन चरण से अलग है।

मैंने मैनुअल इनिशियलाइज़ेशन पर एक और नज़र डाली , और ऐसा लगता है कि इस चाल को करना चाहिए।

मैंने चित्रण करने के लिए एक फील किया है

HTML सरल है:

<html>
    <body>
        <test-directive>This is a test</test-directive>
    </body>
</html>

ए की कमी पर ध्यान दें ng-app । और मेरे पास एक निर्देश है जो कुछ डोम हेरफेर करेगा, इसलिए हम चीजों के क्रम और समय को सुनिश्चित कर सकते हैं।

हमेशा की तरह, एक मॉड्यूल बनाया गया है:

var app = angular.module('app', []);

और यहाँ निर्देश है:

app.directive('testDirective', function() {
    return {
        restrict: 'E',
        template: '<div class="test-directive"><h1><div ng-transclude></div></h1></div>',
        replace: true,
        transclude: true,
        compile: function() {
            console.log("Compiling test-directive");
            return {
                pre: function() { console.log("Prelink"); },
                post: function() { console.log("Postlink"); }
            };
        }
    };
});

हम test-directiveटैग divको कक्षा के साथ बदलने जा रहे हैं test-directive, और इसकी सामग्री को एक में लपेटते हैं h1

मैंने एक संकलन फ़ंक्शन जोड़ा है जो प्री और पोस्ट लिंक फ़ंक्शन दोनों को लौटाता है ताकि हम देख सकें कि ये चीजें कब चलती हैं।

यहाँ कोड के बाकी है:

// The bootstrapping process

var body = document.getElementsByTagName('body')[0];

// Check that our directive hasn't been compiled

function howmany(classname) {
    return document.getElementsByClassName(classname).length;
}

इससे पहले कि हम कुछ भी करें, test-directiveDOM में क्लास के साथ कोई एलिमेंट नहीं होना चाहिए , और ऐसा होने के बाद हमें 1 होना चाहिए।

console.log('before (should be 0):', howmany('test-directive'));

angular.element(document).ready(function() {
    // Bootstrap the body, which loades the specified modules
    // and compiled the DOM.
    angular.bootstrap(body, ['app']);

    // Our app is loaded and the DOM is compiled
    console.log('after (should be 1):', howmany('test-directive'));
});

यह बहुत सीधा है। जब दस्तावेज़ तैयार हो जाता है, तो angular.bootstrapअपने ऐप के मूल तत्व और मॉड्यूल नामों की एक सरणी के साथ कॉल करें ।

वास्तव में, यदि आप किसी runफ़ंक्शन को appमॉड्यूल से जोड़ते हैं देखेंगे कि यह किसी भी संकलन के पूरा होने से पहले ही चलता है।

यदि आप फ़िडेल चलाते हैं और कंसोल देखते हैं, तो आप निम्नलिखित देखेंगे:

before (should be 0): 0 
Compiling test-directive 
Prelink
Postlink
after (should be 1): 1 <--- success!

2
धन्यवाद @satchmorun! लेकिन रनिंग () लिंकिंग भाग के अंत से पहले निष्पादित होता है - बस इसे कुछ कंसोल.लॉग्स के साथ सत्यापित करें।
Lior

अपने आप को उत्सुक था ... मेरे पास एक निर्देश है जो कुछ jQuery डोम प्लगइन्स को लागू करने के लिए आग लगाता है, runनिर्देशन से पहले आग लगाता है और जब आग को चलाता है, तो html सब वहाँ नहीं है
charlietfl

@charlietfl - मैंने मैन्युअल बूटस्ट्रैपिंग में थोड़ा सा खोदा, और यह वास्तव में एक बहुत ही आसान तरीका है जो प्रश्न ढूंढ रहा है। मैंने अपने मूल उत्तर में बहुत लंबा संपादन जोड़ लिया है।
साचमोरुन

5
मैंने पाया कि $timeout( initMyPlugins,0)मेरे निर्देश के भीतर काम करता है, सभी html मैं वहाँ है
charlietfl

@ साचमोरुन, इस अनुवर्ती देखें: stackoverflow.com/questions/14989161/…
लोर

16

जब पृष्ठ लोड हो रहा होता है तो कोणीय ने संकेत देने का एक तरीका प्रदान नहीं किया है, हो सकता है कि "समाप्त" आपके आवेदन पर निर्भर करता है । उदाहरण के लिए, यदि आपके पास विभाजन के पदानुक्रमित पेड़ हैं, तो एक दूसरे को लोड करता है। "समाप्त" का अर्थ होगा कि वे सभी लोड किए गए हैं। किसी भी ढांचे में आपके कोड का विश्लेषण करने और यह समझने में कठिन समय होता है कि सब कुछ हो चुका है, या अभी भी इंतजार कर रहा है। उसके लिए, आपको जाँच करने और निर्धारित करने के लिए एप्लिकेशन-विशिष्ट तर्क देना होगा।


14

मैं एक समाधान के साथ आया हूं जो कि कोणीय आरंभीकरण पूरा होने पर मूल्यांकन करने में अपेक्षाकृत सटीक है।

निर्देश है:

.directive('initialisation',['$rootScope',function($rootScope) {
            return {
                restrict: 'A',
                link: function($scope) {
                    var to;
                    var listener = $scope.$watch(function() {
                        clearTimeout(to);
                        to = setTimeout(function () {
                            console.log('initialised');
                            listener();
                            $rootScope.$broadcast('initialised');
                        }, 50);
                    });
                }
            };
        }]);

इसके बाद bodyतत्व को केवल एक विशेषता के रूप में जोड़ा जा सकता है और फिर उपयोग करने के लिए सुना जाता है$scope.$on('initialised', fn)

यह मानकर काम करता है कि आवेदन तब आरंभिक होता है जब $ जयादा पचने वाले चक्र नहीं होते हैं। $ घड़ी को हर पाचन चक्र कहा जाता है और इसलिए एक टाइमर शुरू किया जाता है (सेटटाइमआउट $ टाइमआउट नहीं होता है इसलिए एक नया पाचन चक्र ट्रिगर नहीं होता है)। यदि कोई पाचन चक्र टाइमआउट के भीतर नहीं होता है, तो यह माना जाता है कि आवेदन को आरंभीकृत किया गया है।

यह स्पष्ट रूप से साचमोरन्स समाधान के रूप में सटीक नहीं है (क्योंकि यह संभव है कि एक पचाने का समय समय से अधिक समय लगता है) लेकिन मेरे समाधान के लिए आपको मॉड्यूल का ट्रैक रखने की आवश्यकता नहीं है जो इसे प्रबंधित करने के लिए बहुत आसान बनाता है (विशेष रूप से बड़ी परियोजनाओं के लिए) )। वैसे भी, मेरी आवश्यकताओं के लिए पर्याप्त सटीक लगता है। आशा करता हूँ की ये काम करेगा।


उत्कृष्ट समाधान। परियोजनाओं के लिए जब एक या दो संपीड़ित फ़ाइलों में सभी कोड बहुत अच्छी तरह से काम करते हैं।
21

1
यह शानदार समाधान है। यदि आपके पास jquery में बहुत सारे कोड हैं और आप कोड को कोणीय चरण में बदलने की कोशिश कर रहे हैं तो यह सही समझ में आता है।
मंगेश Pimpalkar

11

यदि आप कोणीय यूआई राउटर का उपयोग कर रहे हैं , तो आप $viewContentLoadedईवेंट के लिए सुन सकते हैं ।

"$ viewContentLoaded - एक बार दृश्य लोड होने के बाद निकाल दिया जाता है, DOM रेंडर होने के बाद । दृश्य का '$ गुंजाइश' इस घटना का उत्सर्जन करता है।" - लिंक

$scope.$on('$viewContentLoaded', 
function(event){ ... });

3
$ गुंजाइश। $ घड़ी ('$ viewContentLoaded', फ़ंक्शन () ने मेरे लिए चाल बनाई
लुई XIV

2
'जो आपको होना चाहिए' के ​​लिए डाउनवोट किया गया। क्या होगा अगर मैंने कहा "यदि आप कोणीय (जो आपको होना चाहिए) के बजाय प्रतिक्रिया का उपयोग कर रहे हैं ..."? इस पारिस्थितिक तंत्र IMHO में होने के लिए बहुत रवैया नहीं है।
वैलेंटाइन वेस्लेन्क

@ValentinWaeselynck आप बिल्कुल सही हैं। मैंने अपने पूर्वाग्रह को दूर करने के लिए अपने उत्तर को संपादित किया।
जॉर्डन स्कॉल

1
मेरे लिए काम किया! धन्यवाद। मैंने वास्तव में इसे अपने रन फंक्शन में जोड़ा, फिर $ स्कोप को $ रूटस्स्कोप में बदल दिया।
JDavies

2
जैसा कि कोणीय विश्वविद्यालय ने एक अलग उत्तर में बताया है, $ viewContentLoaded मूल रूप से वहां नहीं हो सकती है, लेकिन यह बिल्ट-इन ngRoute प्रदाता में काम करती है, बिल्कुल उसी तरह से। इसे ध्यान में रखते हुए, मुझे लगता है कि यह त्वरित, सरल, पठनीय उत्तर कई (सबसे?) भविष्य के पाठकों की तलाश में होगा।
केविन क्रुमले

3

मैं JQuery के साथ कोणीय के डोम हेरफेर का निरीक्षण करता हूं और मैंने अपने ऐप के लिए एक फिनिश सेट किया है (कुछ प्रकार की पूर्वनिर्धारित और संतोषजनक स्थिति जो मुझे अपने ऐप-सार के लिए आवश्यक है) उदाहरण के लिए मैं अपने एनजी-रिपीटर से 7 परिणाम और आई के लिए उम्मीद करता हूं इस उद्देश्य के लिए setInterval की सहायता से एक अवलोकन फ़ंक्शन सेट करेगा।

$(document).ready(function(){

  var interval = setInterval(function(){

  if($("article").size() == 7){
     myFunction();
     clearInterval(interval);
  }

  },50);

});

3
मैं ऐसा नहीं करूंगा। सामान की जाँच के लिए अंतराल का उपयोग करना अच्छा अभ्यास नहीं है, असाध्य है, और चीजों को बनाने के अन्य तरीके हैं। टाइमर ठोस कार्य करने के लिए होते हैं जिन्हें एक निश्चित समयावधि के बाद होने की आवश्यकता होती है, न कि सामग्री या परिणाम तैयार होने पर "अनुमान लगाने" के लिए।
दुवेद

यह उल्लेख नहीं करने के लिए कि कोणीय प्लेटफॉर्म के खिलाफ एक जेकरी टाइमर का उपयोग करना काउंटर-उत्पादक है- कोणीय में एक टाइमआउट क्लास है और आपको इसका उपयोग करना चाहिए अन्यथा आप दो रूपरेखाओं को दोहरा रहे हैं और यह बहुत जल्दी भ्रमित हो जाता है।
दुवेद

3

यदि आप ngRoute मॉड्यूल का उपयोग नहीं करते हैं , तो आपके पास $ viewContentLoaded घटना नहीं है ।

आप एक और निर्देशन विधि का उपयोग कर सकते हैं:

    angular.module('someModule')
        .directive('someDirective', someDirective);

    someDirective.$inject = ['$rootScope', '$timeout']; //Inject services

    function someDirective($rootScope, $timeout){
        return {
            restrict: "A",
            priority: Number.MIN_SAFE_INTEGER, //Lowest priority
            link    : function(scope, element, attr){
                $timeout(
                    function(){
                        $rootScope.$emit("Some:event");
                    }
                );
            }
        };
    }

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

$ rootScope का उपयोग किया जाता है, क्योंकि यह एप्लिकेशन के किसी भी दायरे में निर्देशन करने की अनुमति देता है और केवल आवश्यक श्रोताओं को सूचित करता है।

$ rootScope। $ emit सभी $ rootScope के लिए एक घटना को आग देगा। $ केवल श्रोताओं पर। दिलचस्प हिस्सा यह है कि $ rootScope। $ प्रसारण सभी $ rootScope को सूचित करेगा। $ पर और साथ ही $ गुंजाइश। $ श्रोताओं के स्रोत पर $।


2

एंगुलर टीम और गितुब मुद्दे के अनुसार :

अब हमारे पास $ viewContentLoaded और $ शामिल करेंContentLoaded ईवेंट हैं जो क्रमशः ng-view और ng- शामिल में उत्सर्जित होती हैं। मुझे लगता है कि यह उतना ही करीब है जितना कि यह जानने के लिए मिल सकता है कि हम संकलन के साथ क्या कर रहे हैं।

इसके आधार पर, ऐसा लगता है कि यह वर्तमान में विश्वसनीय तरीके से करना संभव नहीं है , अन्यथा कोणीय बॉक्स से बाहर की घटना प्रदान करता।

एप्लिकेशन को बूटस्ट्रैप करने का तात्पर्य डाइजेस्ट चक्र को रूट स्कोप पर चलाने से है, और एक डाइजेस्ट चक्र समाप्त होने वाली घटना भी नहीं है।

कोणीय 2 डिजाइन डॉक्स के अनुसार :

मल्टीपल डाइजेस्ट के कारण, घटक को निर्धारित करना और सूचित करना असंभव है कि मॉडल स्थिर है। ऐसा इसलिए है क्योंकि अधिसूचना डेटा को और बदल सकती है, जो बाध्यकारी प्रक्रिया को फिर से शुरू कर सकती है।

इसके अनुसार, यह संभव नहीं है कि यह एक कारण है कि एंगुलर 2 में फिर से लिखने के लिए निर्णय लिया गया था।


2

मेरे पास एक टुकड़ा था जो रूट-इन के बाद / रूटिंग में लोड हो रहा था।

मुझे एक समारोह चलाने की जरूरत थी, जिसके बाद सब-वे लोड हो गया और मैं एक नया निर्देश नहीं लिखना चाहता था और लगा कि आप एक चुटीले प्रयोग कर सकते हैं ngIf

माता-पिता का नियंत्रक आंशिक:

$scope.subIsLoaded = function() { /*do stuff*/; return true; };

उपप्रांत का एच.एम.एल.

<element ng-if="subIsLoaded()"><!-- more html --></element>

1

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

इसके अतिरिक्त, यदि आप प्रतिक्रिया करना चाहते हैं कि सभी निर्देश संकलन / लिंकिंग के दौरान किए गए हैं, तो आप आरंभीकरण तर्क में ऊपर उपयुक्त प्रस्तावित समाधान जोड़ सकते हैं।

module.factory('YourControllerInitService', function() {

    // add your initialization logic here

    // return empty service, because it will not be used
    return {};
});


module.controller('YourController', function (YourControllerInitService) {
});

0

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

$routeProvider
.when("/news", {
    templateUrl: "newsView.html",
    controller: "newsController",
    resolve: {
        message: function(messageService){
            return messageService.getMessage();
    }
}

})

पूर्ण डॉक्स के लिए यहां क्लिक करें - क्रेडिट टू के। स्कॉट एलन


0

हो सकता है कि मैं इस उदाहरण से आपकी मदद कर सकूं

कस्टम फैंसीबॉक्स में मैं अंतर्निर्मित मूल्यों के साथ सामग्री दिखाता हूं।

सेवा में, "ओपन" फैंसीबॉक्स विधि में, मैं करता हूं

open: function(html, $compile) {
        var el = angular.element(html);
     var compiledEl = $compile(el);
        $.fancybox.open(el); 
      }

$ संकलित रिटर्न संकलित डेटा। आप संकलित डेटा की जांच कर सकते हैं

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