Come faccio ad iniettare un controller in un altro controller in AngularJS

Sono nuovo di Angular e sto cercando di capire come fare le cose …

Utilizzando AngularJS, come posso iniettare un controller da utilizzare in un altro controller?

Ho il seguente frammento:

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(); }]); 

Quando eseguo questo, ottengo l’errore:

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

Dovrei anche provare a usare un controller all’interno di un altro controller, o dovrei rendere questo un servizio?

Se si intende ottenere il controller già istanziato di un altro componente e se si sta seguendo un approccio basato su componenti / direttive, è sempre ansible require un controller (istanza di un componente) da un altro componente che segue una determinata gerarchia.

Per esempio:

 //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 ie if(notIsValid(val)){ this.container.disableNext(); } } }, ..., require : { container: '^^wizardContainer' //Require a wizard component's controller which exist in its parent hierarchy. }, ... }); 

Ora l’uso di questi componenti sopra potrebbe essere qualcosa del genere:

   ...     ...   

Ci sono molti modi in cui è ansible impostare richiedono .

(nessun prefisso) – Individua il controller richiesto sull’elemento corrente. Fai un errore se non lo trovi.

? – Tentativo di individuare il controller richiesto o passare null al collegamento fn se non trovato.

^ – Individua il controller richiesto cercando l’elemento e i suoi genitori. Fai un errore se non lo trovi.

^^ – Individua il controller richiesto cercando i genitori dell’elemento. Fai un errore se non lo trovi.

? ^ – Tentativo di localizzare il controller richiesto cercando l’elemento ei suoi genitori o passare null al collegamento fn se non trovato.

? ^^ – Tentativo di localizzare il controller richiesto cercando i genitori dell’elemento o passare null al collegamento fn se non trovato.



Vecchia risposta:

È necessario iniettare il servizio $controller per creare un’istanza di un controller all’interno di un altro controller. Ma sappi che questo potrebbe portare ad alcuni problemi di progettazione. È sempre ansible creare servizi riutilizzabili che seguono la singola responsabilità e iniettarli nei controller di cui si ha bisogno.

Esempio:

 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. }]); 

In ogni caso non è ansible chiamare TestCtrl1.myMethod() perché si è collegato il metodo su $scope e non TestCtrl1.myMethod() del controller.

Se stai condividendo il controller, allora sarebbe sempre meglio fare:

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

e mentre consumano fanno:

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

Nel primo caso in realtà $scope è il tuo modello di vista, e nel secondo caso è l’istanza del controllore stesso.

Suggerirei che la domanda che dovresti porre è come iniettare servizi nei controller. Fat service con skinny controller è una buona regola empirica, ovvero basta usare i controller per incollare il tuo servizio / fabbrica (con la logica aziendale) nelle tue visualizzazioni.

I controllori ottengono la garbage collection sulle modifiche ai route, quindi, ad esempio, se si utilizzano i controller per mantenere la logica aziendale che esegue il rendering di un valore, si perderà lo stato su due pagine se l’utente dell’app fa clic sul pulsante Indietro del browser.

 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(); }]); 

Ecco una demo funzionante di fabbrica iniettata in due controller

Inoltre, suggerirei di leggere questo tutorial su servizi / fabbriche.

Non è necessario importare / inserire il controller in JS. Puoi semplicemente iniettare il controller / controller nidificato tramite il tuo HTML. Ha funzionato per me. Piace :

 
 

Questo funziona meglio nel mio caso, in cui TestCtrl2 ha le sue direttive.

 var testCtrl2 = $controller('TestCtrl2') 

Questo mi dà un errore dicendo errore di iniezione scopeProvider.

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

Questo non funziona davvero se si hanno direttive in ‘TestCtrl1’, quella direttiva ha in realtà un ambito diverso da quello qui creato. Finisci con due istanze di “TestCtrl1”.

La migliore soluzione:-

 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);}) 

// Qui hai ricevuto la prima chiamata del controller senza eseguirla

puoi anche usare $rootScope per chiamare una funzione / metodo del 1 ° controller dal secondo controller come questo,

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

usa typescript per la tua codifica, perché è orientato agli oggetti, tipizzato rigorosamente e facile da mantenere il codice …

per maggiori informazioni su typescipt clicca qui

Ecco un semplice esempio che ho creato per condividere i dati tra due controller usando Typescript …

 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); 

}