Como faço para injetar um controlador em outro controlador no AngularJS

Sou novo no Angular e estou tentando descobrir como fazer as coisas …

Usando o AngularJS, como posso injetar um controlador para ser usado dentro de outro controlador?

Eu tenho o seguinte trecho:

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 eu executo isso, recebo o erro:

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

Deveria eu mesmo estar tentando usar um controlador dentro de outro controlador, ou devo fazer disso um serviço?

Se a sua intenção é obter o controlador já instanciado de outro componente e que, se você estiver seguindo uma abordagem baseada em componente / diretiva, sempre poderá require um controlador (instância de um componente) de outro componente que siga uma determinada hierarquia.

Por exemplo:

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

Agora, o uso desses componentes acima pode ser algo assim:

   ...     ...   

Existem várias maneiras de configurar o require .

(sem prefixo) – localiza o controlador necessário no elemento atual. Lance um erro se não for encontrado.

? – Tente localizar o controlador necessário ou passe null para o link fn se não for encontrado.

^ – Localize o controlador necessário, pesquisando o elemento e seus pais. Lance um erro se não for encontrado.

^^ – Localize o controlador necessário, pesquisando os pais do elemento. Lance um erro se não for encontrado.

? ^ – Tentativa de localizar o controlador necessário, pesquisando o elemento e seus pais ou passar null para o link fn, se não encontrado.

? ^^ – Tente localizar o controlador requerido procurando os pais do elemento, ou passe null para o link fn se não for encontrado.



Resposta antiga:

Você precisa injetar o serviço $controller para instanciar um controlador dentro de outro controlador. Mas esteja ciente de que isso pode levar a alguns problemas de design. Você sempre pode criar serviços reutilizáveis ​​que sigam Responsabilidade Única e injetá-los nos controladores conforme necessário.

Exemplo:

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

Em qualquer caso, você não pode chamar TestCtrl1.myMethod() porque anexou o método no $scope e não na instância do controlador.

Se você está compartilhando o controlador, então seria sempre melhor fazer:

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

e enquanto consumir, faça:

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

No primeiro caso, realmente, o $scope é o seu modelo de visão e, no segundo caso, a própria instância do controlador.

Eu sugiro que a pergunta que você deve fazer é como injetar serviços em controladores. Serviços gordos com controles magros é uma boa regra, ou seja, use apenas controladores para colar seu serviço / fábrica (com a lógica de negócios) em suas visualizações.

Os controladores obtêm o lixo coletado nas alterações de rota, portanto, por exemplo, se você usar controladores para manter a lógica de negócios que renderiza um valor, você perderá o estado em duas páginas se o usuário do aplicativo clicar no botão Voltar do navegador.

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

Aqui está uma demonstração de trabalho de fábrica injetada em dois controladores

Além disso, sugiro ter uma leitura deste tutorial sobre serviços / fábricas.

Não há necessidade de importar / injetar seu controlador no JS. Você pode apenas injetar seu controlador / controlador nested através do seu HTML. Ele funcionou para mim. Gostar :

 
 

Isso funciona melhor no meu caso, onde TestCtrl2 tem suas próprias diretivas.

 var testCtrl2 = $controller('TestCtrl2') 

Isso me dá um erro dizendo erro de injeção scopeProvider.

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

Isso realmente não funciona se você tiver diretivas em ‘TestCtrl1’, que a diretiva realmente tem um escopo diferente daquele criado aqui. Você acaba com duas instâncias de ‘TestCtrl1’.

A melhor solução:-

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

// Aqui você recebeu a primeira chamada do controlador sem executá-la

você também pode usar $rootScope para chamar uma function / método do primeiro controlador do segundo controlador como este,

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

use o typescript para o seu código, porque ele é orientado a objects, estritamente typescript e fácil de manter o código …

para mais informações sobre typescipt clique aqui

Aqui um exemplo simples que criei para compartilhar dados entre dois controladores usando o 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); 

}