angularjs - otro - ng controller que es
¿Cómo inyecto un controlador en otro controlador en AngularJS (7)
Soy nuevo en Angular e intento descubrir cómo hacer las cosas ...
Usando AngularJS, ¿cómo puedo inyectar un controlador para ser utilizado dentro de otro controlador?
Tengo el siguiente fragmento:
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();
}]);
Cuando ejecuto esto, obtengo el error:
Error: [$injector:unpr] Unknown provider: TestCtrl1Provider <- TestCtrl1
http://errors.angularjs.org/1.2.21/$injector/unpr?p0=TestCtrl1Provider%20%3C-%20TestCtrl1
¿Debería incluso intentar usar un controlador dentro de otro controlador, o debería hacer de esto un servicio?
La mejor solucion:-
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);})
// Aquí tienes la primera llamada del controlador sin ejecutarlo
No es necesario importar / inyectar su controlador en JS. Simplemente puede inyectar su controlador / controlador anidado a través de su HTML. Ha funcionado para mí. Me gusta :
<div ng-controller="TestCtrl1">
<div ng-controller="TestCtrl2">
<!-- your code-->
</div>
</div>
Si su intención es obtener el controlador ya instanciado de otro componente y si está siguiendo un enfoque basado en componentes / directivas, siempre puede require
un controlador (instancia de un componente) de otro componente que siga una cierta jerarquía.
Por ejemplo:
//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.
},
...
});
Ahora el uso de estos componentes anteriores podría ser algo como esto:
<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>
Hay muchas formas en que puede configurar require .
(sin prefijo) - Ubique el controlador requerido en el elemento actual. Lanza un error si no lo encuentras.
? - Intentar localizar el controlador requerido o pasar nulo al enlace fn si no se encuentra.
^ - Ubique el controlador requerido buscando el elemento y sus padres. Lanza un error si no lo encuentras.
^^ - Localiza el controlador requerido buscando en los padres del elemento. Lanza un error si no lo encuentras.
? ^ - Intenta localizar el controlador requerido buscando el elemento y sus padres o pasa null al enlace fn si no se encuentra.
? ^^ - Intenta localizar el controlador requerido buscando en los padres del elemento, o pasa null al enlace fn si no se encuentra.
Vieja respuesta:
Necesita inyectar $controller
servicio para instanciar un controlador dentro de otro controlador. Pero tenga en cuenta que esto podría ocasionar algunos problemas de diseño. Siempre puede crear servicios reutilizables que sigan a Single Responsibility e insertarlos en los controladores según lo necesite.
Ejemplo:
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.
}]);
En cualquier caso, no puede llamar a TestCtrl1.myMethod()
porque ha adjuntado el método en $scope
y no en la instancia del controlador.
Si comparte el controlador, entonces siempre sería mejor hacerlo:
.controller(''TestCtrl1'', [''$log'', function ($log) {
this.myMethod = function () {
$log.debug("TestCtrl1 - myMethod");
}
}]);
y mientras consumes haz:
.controller(''TestCtrl2'', [''$scope'', ''$controller'', function ($scope, $controller) {
var testCtrl1ViewModel = $controller(''TestCtrl1'');
testCtrl1ViewModel.myMethod();
}]);
En el primer caso realmente el $scope
es su modelo de vista, y en el segundo caso es la instancia del controlador en sí.
Sugeriría que la pregunta que debería hacerse es cómo inyectar servicios en controladores. Los servicios gordos con controladores delgados son una buena regla empírica, también usan controladores para pegar su servicio / fábrica (con la lógica comercial) en sus vistas.
Los controladores obtienen basura recolectada en cambios de ruta, por lo que, por ejemplo, si usa controladores para mantener la lógica de negocios que rinde un valor, perderá estado en dos páginas si el usuario de la aplicación hace clic en el botón Atrás del 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();
}]);
Aquí hay una demostración funcional de fábrica inyectada en dos controladores
Además, sugiero que lean este tutorial sobre servicios / fábricas.
también puede usar $rootScope
para llamar a una función / método del primer controlador desde el 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 mecanografiado para su codificación, porque está orientado a objetos, estrictamente tipado y fácil de mantener el código ...
para obtener más información sobre typescipt, haga clic aquí
Aquí un ejemplo simple que he creado para compartir datos entre dos controladores 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);
}
<div ng-controller="TestCtrl1">
<div ng-controller="TestCtrl2">
<!-- your code-->
</div>
</div>
Esto funciona mejor en mi caso, donde TestCtrl2 tiene sus propias directivas.
var testCtrl2 = $controller(''TestCtrl2'')
Esto me da un error al decir que el error de inyección de scopeProvider.
var testCtrl1ViewModel = $scope.$new();
$controller(''TestCtrl1'',{$scope : testCtrl1ViewModel });
testCtrl1ViewModel.myMethod();
Esto realmente no funciona si tienes directivas en ''TestCtrl1'', esa directiva en realidad tiene un alcance diferente al creado aquí. Usted termina con dos instancias de ''TestCtrl1''.