मैं किसी नियंत्रक को AngularJS में किसी अन्य नियंत्रक में कैसे इंजेक्ट कर सकता हूं


97

मैं कोणीय के लिए नया हूं और यह जानने की कोशिश कर रहा हूं कि चीजों को कैसे करना है ...

AngularJS का उपयोग करते हुए, मैं एक नियंत्रक को दूसरे नियंत्रक के भीतर उपयोग करने के लिए कैसे इंजेक्ट कर सकता हूं?

मेरे पास निम्नलिखित स्निपेट हैं:

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

app.controller('TestCtrl1', ['$scope', function ($scope) {
    $scope.myMethod = function () {
        console.log("TestCtrl1 - myMethod");
    }
}]);

app.controller('TestCtrl2', ['$scope', 'TestCtrl1', function ($scope, TestCtrl1) {
    TestCtrl1.myMethod();
}]);

जब मैं इसे निष्पादित करता हूं, मुझे त्रुटि मिलती है:

Error: [$injector:unpr] Unknown provider: TestCtrl1Provider <- TestCtrl1
http://errors.angularjs.org/1.2.21/$injector/unpr?p0=TestCtrl1Provider%20%3C-%20TestCtrl1

क्या मुझे किसी अन्य नियंत्रक के अंदर एक नियंत्रक का उपयोग करने की कोशिश करनी चाहिए, या क्या मुझे यह सेवा करनी चाहिए?


2
आप नियंत्रकों को एक दूसरे में इंजेक्ट नहीं कर सकते। हां, आपको TestCtrl1इसके बजाय एक सेवा में बदलना चाहिए ।
Sly_cardinal

सटीक रूप से, सेवाओं का उपयोग करें
मिगुएल मोटा

3
क्या होगा अगर मुझे एक नियंत्रक की संपत्ति को अपडेट करना होगा जो दृश्य को बांधता है। यह गुण किसी अन्य नियंत्रक में होने वाली घटना से प्रभावित होता है।
अंकित तन्ना

जवाबों:


129

यदि आपका इरादा किसी अन्य घटक के पहले से ही तत्काल नियंत्रक को पकड़ना है और यदि आप घटक / निर्देश आधारित दृष्टिकोण का पालन कर रहे हैं, तो आप हमेशा कर सकते हैं require एक नियंत्रक (उदाहरण) का एक निश्चित पदानुक्रम का अनुसरण कर सकते हैं।

उदाहरण के लिए:

//some container component that provides a wizard and transcludes the page components displayed in a wizard
myModule.component('wizardContainer', {
  ...,
  controller : function WizardController() {
    this.disableNext = function() { 
      //disable next step... some implementation to disable the next button hosted by the wizard
    }
  },
  ...
});

//some child component
myModule.component('onboardingStep', {
 ...,
 controller : function OnboadingStepController(){

    this.$onInit = function() {
      //.... you can access this.container.disableNext() function
    }

    this.onChange = function(val) {
      //..say some value has been changed and it is not valid i do not want wizard to enable next button so i call container's disable method i.e
      if(notIsValid(val)){
        this.container.disableNext();
      }
    }
 },
 ...,
 require : {
    container: '^^wizardContainer' //Require a wizard component's controller which exist in its parent hierarchy.
 },
 ...
});

अब इन उपरोक्त घटकों का उपयोग कुछ इस तरह से हो सकता है:

<wizard-container ....>
<!--some stuff-->
...
<!-- some where there is this page that displays initial step via child component -->

<on-boarding-step ...>
 <!--- some stuff-->
</on-boarding-step>
...
<!--some stuff-->
</wizard-container>

कई तरीके हैं जिनसे आपको आवश्यकता हो सकती है

(कोई उपसर्ग नहीं) - वर्तमान तत्व पर आवश्यक नियंत्रक का पता लगाएँ। नहीं मिलने पर त्रुटि फेंको।

? - आवश्यक नियंत्रक का पता लगाने का प्रयास करें या यदि नहीं मिला तो लिंक fn के लिए नल पास करें।

^ - तत्व और उसके माता-पिता की खोज करके आवश्यक नियंत्रक का पता लगाएं। नहीं मिलने पर त्रुटि फेंको।

^ ^ - तत्व के माता-पिता की खोज करके आवश्यक नियंत्रक का पता लगाएं। नहीं मिलने पर त्रुटि फेंको।

^? - तत्व और उसके माता-पिता को खोजकर आवश्यक नियंत्रक का पता लगाने का प्रयास करें या नहीं पाए जाने पर लिंक fn को पास करें।

^ ^ - तत्व के माता-पिता को खोजकर आवश्यक नियंत्रक का पता लगाने का प्रयास करें, या नहीं पाए जाने पर लिंक fn के लिए शून्य पास करें।



पुराना उत्तर:

आपको $controllerएक कंट्रोलर को दूसरे कंट्रोलर के अंदर डालने के लिए सर्विस को इंजेक्ट करना होगा। लेकिन ध्यान रखें कि इससे कुछ डिज़ाइन समस्याएँ हो सकती हैं। आप हमेशा पुन: प्रयोज्य सेवाओं का निर्माण कर सकते हैं जो एकल जिम्मेदारी का पालन करते हैं और उन्हें नियंत्रकों में आवश्यकतानुसार इंजेक्ट करते हैं।

उदाहरण:

app.controller('TestCtrl2', ['$scope', '$controller', function ($scope, $controller) {
   var testCtrl1ViewModel = $scope.$new(); //You need to supply a scope while instantiating.
   //Provide the scope, you can also do $scope.$new(true) in order to create an isolated scope.
   //In this case it is the child scope of this scope.
   $controller('TestCtrl1',{$scope : testCtrl1ViewModel });
   testCtrl1ViewModel.myMethod(); //And call the method on the newScope.
}]);

किसी भी स्थिति में आप कॉल नहीं कर सकते TestCtrl1.myMethod()क्योंकि आपने $scopeकंट्रोलर इंस्टेंस पर विधि को अटैच किया है न कि।

यदि आप नियंत्रक को साझा कर रहे हैं, तो यह करना हमेशा बेहतर होगा: -

.controller('TestCtrl1', ['$log', function ($log) {
    this.myMethod = function () {
        $log.debug("TestCtrl1 - myMethod");
    }
}]);

और उपभोग करते समय:

.controller('TestCtrl2', ['$scope', '$controller', function ($scope, $controller) {
     var testCtrl1ViewModel = $controller('TestCtrl1');
     testCtrl1ViewModel.myMethod();
}]);

पहले मामले में वास्तव में $scopeआपका विचार मॉडल है, और दूसरे मामले में यह नियंत्रक का उदाहरण है।


4
और यह नियंत्रक द्वारा प्रदान की गई कार्यक्षमता पर निर्भर करता है, यदि आप इसे एक व्यूमॉडल की तरह बना रहे हैं, जिसे आपको घटक के रूप में साझा करने की आवश्यकता है, तो यह ठीक है लेकिन अगर यह एक सेवा प्रदाता की कार्यक्षमता से अधिक है तो मैं बस एक सेवा बनाने के साथ जाऊंगा ।
पीएसएल

होना var testCtrl1ViewModel = $scope.$new();चाहिए var testCtrl1ViewModel = $rootScope.$new();? यहां देखें: docs.angularjs.org/guide/controller @PSL
leonsPAPA

ऊपर दिए गए उदाहरण में आप निर्देशक नियंत्रक पर कंटेनर तक पहुंच रहे हैं, लेकिन मुझे यह काम करने के लिए नहीं मिल सकता है। मैं निर्देश पर ही अपने लिंक फ़ंक्शन पर चौथे पैरामीटर के माध्यम से आवश्यक नियंत्रकों का उपयोग कर सकता हूं। लेकिन वे ऊपर दिए गए उदाहरण की तरह निर्देशक नियंत्रक के लिए बाध्य नहीं हैं। क्या किसी और को भी ये समस्या है?
शामी

33

मेरा सुझाव है कि सवाल आप से पूछना चाहिए कि कैसे नियंत्रकों में सेवाओं को इंजेक्ट किया जाए। पतली नियंत्रकों के साथ मोटी सेवाएं अंगूठे का एक अच्छा नियम है, उर्फ ​​बस अपने विचारों में आपकी सेवा / कारखाने (व्यापार तर्क के साथ) को गोंद करने के लिए नियंत्रकों का उपयोग करें।

नियंत्रकों को मार्ग परिवर्तन पर एकत्रित कचरा मिलता है, इसलिए, उदाहरण के लिए, यदि आप नियंत्रक का उपयोग व्यापार तर्क रखने के लिए करते हैं जो एक मान प्रदान करता है, तो दो पृष्ठों पर राज्य खो जाने वाला है यदि ऐप उपयोगकर्ता ब्राउज़र बैक बटन पर क्लिक करता है।

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

app.factory('methodFactory', function () {
    return { myMethod: function () {
            console.log("methodFactory - myMethod");
    };
};

app.controller('TestCtrl1', ['$scope', 'methodFactory', function ($scope,methodFactory) {  //Comma was missing here.Now it is corrected.
    $scope.mymethod1 = methodFactory.myMethod();
}]);

app.controller('TestCtrl2', ['$scope', 'methodFactory', function ($scope, methodFactory) {
    $scope.mymethod2 = methodFactory.myMethod();
}]);

यहाँ दो नियंत्रक में फैक्ट्री का एक कार्यशील डेमो डाला गया है

इसके अलावा, मेरा सुझाव है कि सेवाओं / कारखानों पर इस ट्यूटोरियल को पढ़ें।


13

जेएस में अपने नियंत्रक को आयात / इंजेक्ट करने की कोई आवश्यकता नहीं है। आप बस अपने HTML के माध्यम से अपने नियंत्रक / नेस्टेड नियंत्रक को इंजेक्ट कर सकते हैं। यह मेरे लिए काम कर रहा है। पसंद :

<div ng-controller="TestCtrl1">
    <div ng-controller="TestCtrl2">
      <!-- your code--> 
    </div> 
</div>

2
सच ... लेकिन मैं अभी भी सभी सामान्य तत्वों को एक सेवा में रखना और संबंधित नियंत्रक को सेवा इंजेक्ट करना बेहतर समझता हूं।
नील

-1
<div ng-controller="TestCtrl1">
    <div ng-controller="TestCtrl2">
      <!-- your code--> 
    </div> 
</div>

यह मेरे मामले में सबसे अच्छा काम करता है, जहां TestCtrl2 के अपने निर्देश हैं।

var testCtrl2 = $controller('TestCtrl2')

यह मुझे एक त्रुटि कह रही है गुंजाइश गुंजाइश इंजेक्शन त्रुटि।

   var testCtrl1ViewModel = $scope.$new();
   $controller('TestCtrl1',{$scope : testCtrl1ViewModel });
   testCtrl1ViewModel.myMethod(); 

यह वास्तव में काम नहीं करता है यदि आपके पास 'TestCtrl1' में निर्देश हैं, तो यह निर्देश वास्तव में यहां बनाए गए इस से अलग गुंजाइश है। आप 'TestCtrl1' के दो उदाहरणों के साथ समाप्त होते हैं।


-1

सबसे अच्छा समाधान:-

angular.module("myapp").controller("frstCtrl",function($scope){$scope.name="Atul Singh";}).controller("secondCtrl",function($scope){angular.extend(this, $controller('frstCtrl', {$scope:$scope}));console.log($scope);})

// यहां आपको पहला कंट्रोलर कॉल मिला है उसे एक्जीक्यूट किए बिना


-1

आप $rootScopeइस तरह से दूसरे कंट्रोलर से 1 कंट्रोलर के फंक्शन / मेथड को कॉल करने के लिए भी इस्तेमाल कर सकते हैं ।

.controller('ctrl1', function($rootScope, $scope) {
     $rootScope.methodOf2ndCtrl();
     //Your code here. 
})

.controller('ctrl2', function($rootScope, $scope) {
     $rootScope.methodOf2ndCtrl = function() {
     //Your code here. 
}
})

1
डाउनवोट: यह सिर्फ खराब कोडिंग है: आप केवल अपने फ़ंक्शन को वैश्विक बना रहे हैं। बेहतर एंगुलर को पूरी तरह से छोड़ दें यदि यह वह तरीका है जिसे आप कोड करना चाहते हैं ... तो अधिकांश अन्य उत्तरों द्वारा सुझाई गई सेवा का उपयोग करें।
हैमरएनएल

यह अनुशंसित नहीं है। $ rootScope कोड को अनाड़ी बनाता है और दीर्घकालिक में समस्याओं की ओर ले जाता है।
हर्षित पंत

-2

अपने कोडिंग के लिए टाइपस्क्रिप्ट का उपयोग करें, क्योंकि यह ऑब्जेक्ट उन्मुख है, कड़ाई से टाइप किया गया है और कोड को बनाए रखना आसान है ...

टाइपसेट के बारे में अधिक जानकारी के लिए यहां क्लिक करें

यहां एक सरल उदाहरण मैंने टाइपस्क्रिप्ट का उपयोग करके दो नियंत्रक के बीच डेटा साझा करने के लिए बनाया है ...

module Demo {
//create only one module for single Applicaiton
angular.module('app', []);
//Create a searvie to share the data
export class CommonService {
    sharedData: any;
    constructor() {
        this.sharedData = "send this data to Controller";
    }
}
//add Service to module app
angular.module('app').service('CommonService', CommonService);

//Create One controller for one purpose
export class FirstController {
    dataInCtrl1: any;
    //Don't forget to inject service to access data from service
    static $inject = ['CommonService']
    constructor(private commonService: CommonService) { }
    public getDataFromService() {
        this.dataInCtrl1 = this.commonService.sharedData;
    }
}
//add controller to module app
angular.module('app').controller('FirstController', FirstController);
export class SecondController {
    dataInCtrl2: any;
    static $inject = ['CommonService']
    constructor(private commonService: CommonService) { }
    public getDataFromService() {
        this.dataInCtrl2 = this.commonService.sharedData;
    }
}
angular.module('app').controller('SecondController', SecondController);

}

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