¿Puede un controlador AngularJS llamar a otro?

Resuelto BanksySan asked hace 12 años • 14 respuestas

¿Es posible que un controlador utilice otro?

Por ejemplo:

Este documento HTML simplemente imprime un mensaje entregado por el MessageCtrlcontrolador en el messageCtrl.jsarchivo.

<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, DateCtrlque le devolviera la fecha en un formato específico MessageCtrl, ¿cómo se haría esto? El marco de DI parece preocuparse por XmlHttpRequestsel acceso a los servicios.

BanksySan avatar Feb 15 '12 19:02 BanksySan
Aceptado

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.

Vojta avatar Feb 23 '2012 05:02 Vojta

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'];
adardesign avatar Aug 07 '2012 13:08 adardesign

Si desea llamar un controlador a otro, hay cuatro métodos disponibles

  1. $rootScope.$emit() y $rootScope.$broadcast()
  2. Si el segundo controlador es secundario, puede utilizar la comunicación entre padres e hijos.
  3. Usar servicios
  4. 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.

Shubham Nigam avatar Jul 17 '2015 06:07 Shubham Nigam