व्यू लोड होने पर AngularJS इनिशियलाइज़ेशन कोड चलाना


92

जब मैं एक दृश्य लोड करता हूं, तो मैं इसके संबंधित नियंत्रक में कुछ आरंभीकरण कोड चलाना चाहता हूं।

ऐसा करने के लिए, मैंने अपने दृश्य के मुख्य तत्व पर एनजी-इनिट निर्देश का उपयोग किया है:

<div ng-init="init()">
  blah
</div>

और नियंत्रक में:

$scope.init = function () {
    if ($routeParams.Id) {
        //get an existing object
        });
    } else {
       //create a new object
    }

    $scope.isSaving = false;
}

पहला सवाल: क्या यह करने का सही तरीका है?

अगली बात, मुझे घटनाओं के अनुक्रम के साथ एक समस्या है। दृश्य में मेरे पास एक 'सेव' बटन है, जो ng-disabledनिर्देश का उपयोग करता है जैसे:

<button ng-click="save()" ng-disabled="isClean()">Save</button>

isClean()समारोह नियंत्रक में परिभाषित किया गया है:

$scope.isClean = function () {
    return $scope.hasChanges() && !$scope.isSaving;
}

जैसा कि आप देख सकते हैं, यह $scope.isSavingध्वज का उपयोग करता है , जिसे init()फ़ंक्शन में प्रारंभ किया गया था ।

समस्या: जब दृश्य लोड किया जाता है, isClean समारोह कहा जाता है से पहलेinit() समारोह, इसलिए झंडा isSavingहै undefined। इसे रोकने के लिए मैं क्या कर सकता हूं?

जवाबों:


136

जब आपका दृश्य लोड होता है, तो इसका संबद्ध नियंत्रक करता है। उपयोग करने के बजाय ng-init, अपनी init()विधि को अपने नियंत्रक में कहें :

$scope.init = function () {
    if ($routeParams.Id) {
        //get an existing object
    } else {
        //create a new object
    }
    $scope.isSaving = false;
}
...
$scope.init();

चूंकि आपका नियंत्रक पहले चलता है ng-init, यह आपके दूसरे मुद्दे को भी हल करता है।

बेला


जैसा कि John David Fiveउल्लेख किया गया है, आप $scopeइस विधि को निजी बनाने के लिए इसे संलग्न नहीं करना चाह सकते हैं ।

var init = function () {
    // do something
}
...
init();

JsFiddle देखें


यदि आप कुछ डेटा के प्रीसेट होने का इंतजार करना चाहते हैं, तो उस डेटा रिक्वेस्ट को हल करने के लिए ले जाएं या उस संग्रह या ऑब्जेक्ट पर एक वॉकर जोड़ें और जब आपका डेटा आपके इनिट मानदंडों को पूरा करता है तो अपने इनिट विधि को कॉल करें। मैं आमतौर पर द्रष्टा को हटा देता हूं जब मेरे डेटा की आवश्यकताएं पूरी हो जाती हैं, तो यह init फ़ंक्शन बेतरतीब ढंग से फिर से नहीं चलता है अगर आपके डेटा में परिवर्तन देखने और आपके इनिट विधि को चलाने के लिए आपके मानदंडों को पूरा करता है।

var init = function () {
    // do something
}
...
var unwatch = scope.$watch('myCollecitonOrObject', function(newVal, oldVal){
                    if( newVal && newVal.length > 0) {
                        unwatch();
                        init();
                    }
                });

8
यदि आपको इनिशियलाइज़ेशन चलाने के लिए कुछ मॉडलों के डेटा की आवश्यकता हो तो क्या होगा? या रेंडर करते समय पृष्ठ पर उपलब्ध कुछ डेटा, ताकि इनिशियलाइज़ेशन काम कर सके?
यूजीन

38
एक init फ़ंक्शन को $ स्कोप में संलग्न करने की आवश्यकता नहीं है। अपने init फ़ंक्शन को निजी बनाएं। आप कभी भी इनिट फ़ंक्शन को एक से अधिक बार चलाना नहीं चाहते हैं, इसलिए इसे $ स्कोप पर उजागर न करें।
जॉन डेविड फाइव

2
जब भी मेरा दृश्य दिखाया जाता है, तो मैं init फ़ंक्शन चलाना चाहता हूं, लेकिन मुझे कोई सुराग नहीं है कि, फ़ंक्शन केवल एक बार चलाया जाता है। किसी भी विचार मैं इसे हर पृष्ठ / टेम्पलेट लोड पर कैसे चला सकता हूं?
जोरे

9
मैं कोणीय विशेषज्ञ नहीं हूं, लेकिन यह दृष्टिकोण परीक्षण के लिए बेकार है, चूंकि init () को बस नियंत्रक तात्कालिकता कहा जाता है ... दूसरे शब्दों में, जब आपको नियंत्रक की एक विधि का परीक्षण करने की आवश्यकता होती है, तो init () को भी कहा जाता है। परीक्षणों को तोड़ना!
वैगनर लियोनार्डी

1
@WagnerLeonardi ने क्या कहा। यह दृष्टिकोण आपके "निजी" init () विधि को काफी कठिन बनाता है।
स्टीवन रोजर्स

36

AngularJS 1.5 के बाद से हमें उपयोग करना चाहिए$onInit जो किसी भी AngularJS घटक पर उपलब्ध है। घटक जीवन चक्र प्रलेखन से लिया गया v1 से पहले से ही प्रचलित तरीके से:

$ onInit () - प्रत्येक कंट्रोलर को एक कंट्रोलर के सभी तत्वों के निर्माण के बाद कॉल किया जाता है और उनके बाइंडिंग को इनिशियलाइज़ किया जाता है (और इस तत्व पर निर्देशों के लिए पूर्व और पोस्ट लिंकिंग फ़ंक्शंस से पहले)। अपने कंट्रोलर के लिए इनिशियलाइज़ेशन कोड डालने के लिए यह एक अच्छी जगह है।

var myApp = angular.module('myApp',[]);
myApp.controller('MyCtrl', function ($scope) {

    //default state
    $scope.name = '';

    //all your init controller goodness in here
    this.$onInit = function () {
      $scope.name = 'Superhero';
    }
});

>> फिडेल डेमो


घटक जीवन चक्र का उपयोग करने का एक उन्नत उदाहरण:

घटक जीवनचक्र हमें अच्छे तरीके से घटक सामान को संभालने की क्षमता देता है। यह हमें एक घटक के "init", "परिवर्तन" या "नष्ट" के लिए घटनाओं को बनाने की अनुमति देता है। इस तरह हम सामान का प्रबंधन करने में सक्षम हैं जो एक घटक के जीवनचक्र पर निर्भर करता है। यह छोटा उदाहरण एक $rootScopeघटना श्रोता को पंजीकृत करने और अपंजीकृत करने के लिए दिखाता है $on। यह जानकर कि, किसी घटना $onपर $rootScopeबाँधने से कोई नुकसान नहीं होगा जब नियंत्रक दृश्य में अपना संदर्भ खो देता है या नष्ट हो जाता है तो हमें एक $rootScope.$onश्रोता को मैन्युअल रूप से नष्ट करने की आवश्यकता होती है । उस सामान को रखने के लिए एक अच्छी जगह $onDestroyएक घटक का जीवनचक्र है:

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

myApp.controller('MyCtrl', function ($scope, $rootScope) {

  var registerScope = null;

  this.$onInit = function () {
    //register rootScope event
    registerScope = $rootScope.$on('someEvent', function(event) {
        console.log("fired");
    });
  }

  this.$onDestroy = function () {
    //unregister rootScope event by calling the return function
    registerScope();
  }
});

>> फिडल डेमो


17

या आप नियंत्रक में सिर्फ इनलाइन को इनिशियलाइज़ कर सकते हैं। यदि आप नियंत्रक के लिए एक इनिट फ़ंक्शन का उपयोग आंतरिक करते हैं, तो इसे दायरे में परिभाषित करने की आवश्यकता नहीं है। वास्तव में, यह आत्म निष्पादन हो सकता है:

function MyCtrl($scope) {
    $scope.isSaving = false;

    (function() {  // init
        if (true) { // $routeParams.Id) {
            //get an existing object
        } else {
            //create a new object
        }
    })()

    $scope.isClean = function () {
       return $scope.hasChanges() && !$scope.isSaving;
    }

    $scope.hasChanges = function() { return false }
}

1
क्या कोई कारण है कि इनिट कोड एक अनाम बंद में है?
एडम टोले

@AdamTolley कोई विशेष कारण नहीं है। वह सिर्फ एक फ़ंक्शन को परिभाषित करता है और तुरंत उसे कॉल करता है, बिना किसी संस्करण के लिए बाध्य किए।
टायर सिप

7
आप इस तरह से निजी init () फ़ंक्शन को ठीक से कैसे जांच सकते हैं?
स्टीवन रोजर्स

केवल सार्वजनिक सदस्यों का परीक्षण किया जाता है। यूनिट परीक्षण इस बात पर निर्भर नहीं होना चाहिए कि अपेक्षित परिणाम प्राप्त करने के लिए कौन से वर्ग निजी तौर पर करते हैं।
फिल

14

मैं अपनी परियोजनाओं में निम्नलिखित टेम्पलेट का उपयोग करता हूं:

angular.module("AppName.moduleName", [])

/**
 * @ngdoc controller
 * @name  AppName.moduleName:ControllerNameController
 * @description Describe what the controller is responsible for.
 **/
    .controller("ControllerNameController", function (dependencies) {

        /* type */ $scope.modelName = null;
        /* type */ $scope.modelName.modelProperty1 = null;
        /* type */ $scope.modelName.modelPropertyX = null;

        /* type */ var privateVariable1 = null;
        /* type */ var privateVariableX = null;

        (function init() {
            // load data, init scope, etc.
        })();

        $scope.modelName.publicFunction1 = function () /* -> type  */ {
            // ...
        };

        $scope.modelName.publicFunctionX = function () /* -> type  */ {
            // ...
        };

        function privateFunction1() /* -> type  */ {
            // ...
        }

        function privateFunctionX() /* -> type  */ {
            // ...
        }

    });

यह साफ दिखता है, लेकिन iffe आपको उन तरीकों को चलाने से रोकता है जिन्हें आप गुंजाइश पर परिभाषित कर रहे हैं, जो कि अक्सर हमें क्या करना है, उन्हें एक बार स्टार्टअप पर चलाएं, और फिर उन्हें चलाने के लिए सक्षम होने के लिए भी गुंजाइश पर रखें फिर से उपयोगकर्ता द्वारा आवश्यक
chrismarx

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