¿Puede un controlador AngularJS llamar a otro?
¿Es posible que un controlador utilice otro?
Por ejemplo:
Este documento HTML simplemente imprime un mensaje entregado por el MessageCtrl
controlador en el messageCtrl.js
archivo.
<html xmlns:ng="http://angularjs.org/">
<head>
<meta charset="utf-8" />
<title>Inter Controller Communication</title>
</head>
<body>
<div ng:controller="MessageCtrl">
<p>{{message}}</p>
</div>
<!-- Angular Scripts -->
<script src="http://code.angularjs.org/angular-0.9.19.js" ng:autobind></script>
<script src="js/messageCtrl.js" type="text/javascript"></script>
</body>
</html>
El archivo del controlador contiene el siguiente código:
function MessageCtrl()
{
this.message = function() {
return "The current date is: " + new Date().toString();
};
}
Que simplemente imprime la fecha actual;
Si tuviera que agregar otro controlador, DateCtrl
que le devolviera la fecha en un formato específico MessageCtrl
, ¿cómo se haría esto? El marco de DI parece preocuparse por XmlHttpRequests
el acceso a los servicios.
Hay varias formas de comunicarse entre controladores.
Probablemente el mejor sea compartir un servicio:
function FirstController(someDataService)
{
// use the data service, bind to template...
// or call methods on someDataService to send a request to server
}
function SecondController(someDataService)
{
// has a reference to the same instance of the service
// so if the service updates state for example, this controller knows about it
}
Otra forma es emitir un evento en el alcance:
function FirstController($scope)
{
$scope.$on('someEvent', function(event, args) {});
// another controller or even directive
}
function SecondController($scope)
{
$scope.$emit('someEvent', args);
}
En ambos casos, podrás comunicarte también con cualquier directiva.
Vea este violín: http://jsfiddle.net/simpulton/XqDxG/
Mire también el siguiente vídeo: Comunicación entre controladores
HTML:
<div ng-controller="ControllerZero">
<input ng-model="message" >
<button ng-click="handleClick(message);">LOG</button>
</div>
<div ng-controller="ControllerOne">
<input ng-model="message" >
</div>
<div ng-controller="ControllerTwo">
<input ng-model="message" >
</div>
javascript:
var myModule = angular.module('myModule', []);
myModule.factory('mySharedService', function($rootScope) {
var sharedService = {};
sharedService.message = '';
sharedService.prepForBroadcast = function(msg) {
this.message = msg;
this.broadcastItem();
};
sharedService.broadcastItem = function() {
$rootScope.$broadcast('handleBroadcast');
};
return sharedService;
});
function ControllerZero($scope, sharedService) {
$scope.handleClick = function(msg) {
sharedService.prepForBroadcast(msg);
};
$scope.$on('handleBroadcast', function() {
$scope.message = sharedService.message;
});
}
function ControllerOne($scope, sharedService) {
$scope.$on('handleBroadcast', function() {
$scope.message = 'ONE: ' + sharedService.message;
});
}
function ControllerTwo($scope, sharedService) {
$scope.$on('handleBroadcast', function() {
$scope.message = 'TWO: ' + sharedService.message;
});
}
ControllerZero.$inject = ['$scope', 'mySharedService'];
ControllerOne.$inject = ['$scope', 'mySharedService'];
ControllerTwo.$inject = ['$scope', 'mySharedService'];
Si desea llamar un controlador a otro, hay cuatro métodos disponibles
- $rootScope.$emit() y $rootScope.$broadcast()
- Si el segundo controlador es secundario, puede utilizar la comunicación entre padres e hijos.
- Usar servicios
- Tipo de truco, con la ayuda de angular.element()
1. $rootScope.$emit() y $rootScope.$broadcast()
El controlador y su alcance pueden destruirse, pero $rootScope permanece en toda la aplicación, es por eso que tomamos $rootScope porque $rootScope es el padre de todos los alcances.
Si está realizando una comunicación de padre a hijo e incluso el niño quiere comunicarse con sus hermanos, puede usar $broadcast
Si está realizando una comunicación de niño a padre y no hay hermanos involucrados, puede usar $rootScope.$emit
HTML
<body ng-app="myApp">
<div ng-controller="ParentCtrl" class="ng-scope">
// ParentCtrl
<div ng-controller="Sibling1" class="ng-scope">
// Sibling first controller
</div>
<div ng-controller="Sibling2" class="ng-scope">
// Sibling Second controller
<div ng-controller="Child" class="ng-scope">
// Child controller
</div>
</div>
</div>
</body>
Código Angularjs
var app = angular.module('myApp',[]);//We will use it throughout the example
app.controller('Child', function($rootScope) {
$rootScope.$emit('childEmit', 'Child calling parent');
$rootScope.$broadcast('siblingAndParent');
});
app.controller('Sibling1', function($rootScope) {
$rootScope.$on('childEmit', function(event, data) {
console.log(data + ' Inside Sibling one');
});
$rootScope.$on('siblingAndParent', function(event, data) {
console.log('broadcast from child in parent');
});
});
app.controller('Sibling2', function($rootScope) {
$rootScope.$on('childEmit', function(event, data) {
console.log(data + ' Inside Sibling two');
});
$rootScope.$on('siblingAndParent', function(event, data) {
console.log('broadcast from child in parent');
});
});
app.controller('ParentCtrl', function($rootScope) {
$rootScope.$on('childEmit', function(event, data) {
console.log(data + ' Inside parent controller');
});
$rootScope.$on('siblingAndParent', function(event, data) {
console.log('broadcast from child in parent');
});
});
En el código anterior, la consola de $emit 'childEmit' no llamará dentro de los hermanos secundarios y llamará solo dentro de los padres, donde $broadcast será llamado dentro de los hermanos y padres también. Este es el lugar donde el rendimiento entra en acción.$emit es Es preferible si está utilizando la comunicación entre padres e hijos porque se salta algunos controles sucios.
2. Si el segundo controlador es secundario, puede utilizar la comunicación entre padres e hijos.
Es uno de los mejores métodos. Si desea establecer una comunicación entre padres e hijos donde el niño quiere comunicarse con los padres inmediatos , entonces no necesitaría ningún tipo de $broadcast o $emit, pero si desea realizar una comunicación de padres a hijos, entonces debe hacerlo. use el servicio o $broadcast
Por ejemplo HTML: -
<div ng-controller="ParentCtrl">
<div ng-controller="ChildCtrl">
</div>
</div>
angularjs
app.controller('ParentCtrl', function($scope) {
$scope.value='Its parent';
});
app.controller('ChildCtrl', function($scope) {
console.log($scope.value);
});
Siempre que utilice la comunicación entre padres e hijos, Angularjs buscará una variable dentro del niño. Si no está presente dentro, elegirá ver los valores dentro del controlador principal.
3.Usar servicios
AngularJS admite los conceptos de "separación de preocupaciones" utilizando la arquitectura de servicios. Los servicios son funciones de JavaScript y son responsables de realizar tareas específicas únicamente. Esto los convierte en una entidad individual que se puede mantener y probar . Los servicios se utilizan para inyectar utilizando el mecanismo de inyección de dependencia de Angularjs.
Código angularjs:
app.service('communicate',function(){
this.communicateValue='Hello';
});
app.controller('ParentCtrl',function(communicate){//Dependency Injection
console.log(communicate.communicateValue+" Parent World");
});
app.controller('ChildCtrl',function(communicate){//Dependency Injection
console.log(communicate.communicateValue+" Child World");
});
Dará como resultado Hello Child World y Hello Parent World. Según los documentos de Angular de servicios Singletons: cada componente que depende de un servicio obtiene una referencia a la instancia única generada por la fábrica de servicios .
4. Tipo de truco: con la ayuda de angular.element()
Este método obtiene alcance() del elemento mediante su Id/único método class.angular.element() devuelve el elemento y alcance() proporciona la variable $scope de otra variable usando la variable $scope de un controlador dentro de otro no es una buena práctica.
HTML: -
<div id='parent' ng-controller='ParentCtrl'>{{varParent}}
<span ng-click='getValueFromChild()'>Click to get ValueFormChild</span>
<div id='child' ng-controller='childCtrl'>{{varChild}}
<span ng-click='getValueFromParent()'>Click to get ValueFormParent </span>
</div>
</div>
Angularjs: -
app.controller('ParentCtrl',function($scope){
$scope.varParent="Hello Parent";
$scope.getValueFromChild=function(){
var childScope=angular.element('#child').scope();
console.log(childScope.varChild);
}
});
app.controller('ChildCtrl',function($scope){
$scope.varChild="Hello Child";
$scope.getValueFromParent=function(){
var parentScope=angular.element('#parent').scope();
console.log(parentScope.varParent);
}
});
En el código anterior, los controladores muestran su propio valor en HTML y cuando haga clic en el texto obtendrá los valores correspondientes en la consola. Si hace clic en el intervalo de controladores principales, el navegador mostrará el valor de la consola del niño y viceversa.