Pregunta ¿Puede un controlador AngularJS llamar a otro?


¿Es posible tener un controlador usar 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 entregó la fecha en un formato específico de nuevo a MessageCtrl¿Cómo se puede hacer esto? El marco DI parece estar relacionado con XmlHttpRequests y acceder a los servicios.


549
2018-02-15 12:31


origen


Respuestas:


Hay varias formas de comunicarse entre controladores.

El mejor es probablemente 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, puede comunicarse con cualquier directiva también.


680
2018-02-23 05:59



Mira este violín http://jsfiddle.net/simpulton/XqDxG/

También mira el siguiente video: 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'];

119
2017-08-07 13:40



Aquí hay un ejemplo de una página de dos controladores que comparten datos del servicio:

<!doctype html>
<html ng-app="project">
<head>
    <title>Angular: Service example</title>
    <script src="http://code.angularjs.org/angular-1.0.1.js"></script>
    <script>
var projectModule = angular.module('project',[]);

projectModule.factory('theService', function() {  
    return {
        thing : {
            x : 100
        }
    };
});

function FirstCtrl($scope, theService) {
    $scope.thing = theService.thing;
    $scope.name = "First Controller";
}

function SecondCtrl($scope, theService) {   
    $scope.someThing = theService.thing; 
    $scope.name = "Second Controller!";
}
    </script>
</head>
<body>  
    <div ng-controller="FirstCtrl">
        <h2>{{name}}</h2>
        <input ng-model="thing.x"/>         
    </div>

    <div ng-controller="SecondCtrl">
        <h2>{{name}}</h2>
        <input ng-model="someThing.x"/>             
    </div>
</body>
</html>

También aquí: https://gist.github.com/3595424


52
2017-09-02 06:51



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

  1. $ rootScope. $ emitir () y $ rootScope. $ broadcast ()
  2. Si el segundo controlador es secundario, puede usar la comunicación padre-hijo.
  3. Usa los servicios
  4. Tipo de pirateo - con la ayuda de angular.element ()

1. $ rootScope. $ Emitir () y $ rootScope. $ Broadcast ()

El controlador y su alcance pueden ser destruidos, pero el $ rootScope permanece en la aplicación, por eso estamos tomando $ rootScope porque $ rootScope es padre de todos los ámbitos.

Si estás comunicando de padres a hijos e incluso el niño quiere comunicarse con sus hermanos, puedes usar $ broadcast

Si está realizando una comunicación de hijo a padre, no hay hermanos invocados, entonces puede usar $ rootScope. $ Emitir

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 la consola de código anterior de $ emitir 'childEmit' no se llamará dentro de los hermanos secundarios y se llamará dentro de solo parent, donde $ broadcast se llamará también dentro de los hermanos y los padres. Este es el lugar donde el rendimiento entra en acción. $ Emit is Preferible, si está utilizando la comunicación de niño a padre porque omite algunos controles sucios.

2. Si el segundo controlador es secundario, puede usar la comunicación de Child Parent

Es uno de los mejores métodos, si quieres hacer comunicación entre padres y niños donde el niño quiere comunicarse con padre inmediato entonces no necesitaría ningún tipo $ broadcast o $ emit, pero si desea hacer la comunicación de padre a hijo, entonces tiene que usar 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 esté utilizando la comunicación de niño a padre, Angularjs buscará una variable dentro de niño, si no está presente, entonces elegirá ver los valores dentro del controlador principal.

3. Utilizar servicios

AngularJS apoya los conceptos de "Separación de preocupaciones" utilizando servicios de arquitectura. Los servicios son funciones de JavaScript y son responsables de realizar solo tareas específicas. Esto los convierte en entidad individual cual es mantenible y comprobable.Los servicios solían inyectarse usando 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á salida a Hello Child World y Hello Parent World. De acuerdo con los documentos angulares de servicios Singletons: cada componente que depende de un servicio recibe una referencia a la única instancia generada por la fábrica de servicios..

4. Tipo de pirateo - con la ayuda de angular.element ()

Este método obtiene scope () del elemento por su Id / clase única. El método devuelve elemento y scope () da $ scope variable de otra variable utilizando $ scope variable 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 la parte superior, los controladores de códigos muestran su propio valor en Html y cuando haga clic en el texto, obtendrá los valores en la consola en consecuencia. Si hace clic en la extensión de los controladores principales, el navegador conciliará el valor de secundario y viceversa.


46
2017-07-17 06:17



Si está buscando emitir y difundir eventos para compartir datos o funciones de llamada a través de controladores, por favor mira esto enlazar: y verifica la respuesta zbynour (respuesta con votos máximos). ¡Estoy citando su respuesta!

Si el alcance de firstCtrl es principal del segundo ámbito deCtrl, su código debería funcionar reemplazando $ emitir por $ broadcast en firstCtrl:

function firstCtrl($scope){
    $scope.$broadcast('someEvent', [1,2,3]);
}

function secondCtrl($scope){
    $scope.$on('someEvent', function(event, mass) {console.log(mass)});
}

En caso de que no exista una relación padre-hijo entre sus ámbitos, puede inyectar $ rootScope en el controlador y transmitir el evento a todos los ámbitos secundarios (es decir, también a secondCtrl).

function firstCtrl($rootScope){
    $rootScope.$broadcast('someEvent', [1,2,3]);
}

Finalmente, cuando necesite enviar el evento desde el controlador hijo a los ámbitos hacia arriba, puede usar $ scope. $ Emit. Si el alcance de firstCtrl es principal del segundo ámbito deCtrl:

function firstCtrl($scope){
    $scope.$on('someEvent', function(event, data) { console.log(data); });
}

function secondCtrl($scope){
    $scope.$emit('someEvent', [1,2,3]);
}

31
2017-10-15 13:26



Dos violines más: (enfoque sin servicio)

1) Para el controlador Parent-Child - Usando $scope del controlador principal para emitir / transmitir eventos.       http://jsfiddle.net/laan_sachin/jnj6y/

2) Usando $rootScope a través de controladores no relacionados.       http://jsfiddle.net/VxafF/


24
2017-10-07 17:07



En realidad, usar emitir y emitir es ineficiente porque el evento sube y baja de la jerarquía de alcance, que puede degradarse fácilmente en una botella de rendimiento para una aplicación compleja.

Sugeriría usar un servicio. Así es como lo implementé recientemente en uno de mis proyectos: https://gist.github.com/3384419.

Idea básica: registrar un bus pub-sub / evento como servicio. Luego, inserte ese bus de eventos donde sea que necesite suscribirse o publicar eventos / temas.


16
2017-08-18 04:32