Pregunta Trabajando con $ scope. $ Emit y $ scope. $ On


¿Cómo puedo enviar mi $scope objeto de un controlador a otro usando .$emit y .$on métodos?

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

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

No funciona como creo que debería. Como hacer $emit y $on ¿trabajo?


844
2018-01-24 13:03


origen


Respuestas:


En primer lugar, la relación de alcance entre padres e hijos sí importa. Tienes dos posibilidades para emitir algún evento:

  • $broadcast - envía el evento hacia abajo a todos los ámbitos secundarios,
  • $emit - distribuye el evento hacia arriba a través de la jerarquía de alcance.

No sé nada sobre la relación de sus controladores (ámbitos), pero hay varias opciones:

  1. Si el alcance de firstCtrl es padre de la secondCtrl alcance, su código debería trabajar reemplazando $emit 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); });
    }
    
  2. En caso de que no haya una relación padre-hijo entre tus ámbitos, puede inyectar $rootScope en el controlador y transmitir el evento a todos los ámbitos secundarios (es decir, secondCtrl)

    function firstCtrl($rootScope)
    {
        $rootScope.$broadcast('someEvent', [1,2,3]);
    }
    
  3. Finalmente, cuando necesite enviar el evento desde el controlador de niño para alcances hacia arriba puede usar $scope.$emit. Si el alcance de firstCtrl es padre de la secondCtrl alcance:

    function firstCtrl($scope)
    {
        $scope.$on('someEvent', function(event, data) { console.log(data); });
    }
    
    function secondCtrl($scope)
    {
        $scope.$emit('someEvent', [1,2,3]);
    }
    

1465
2018-01-24 13:41



Además, sugeriría una cuarta opción como una mejor alternativa a las opciones propuestas por @zbynour.

Utilizar $rootScope.$emit más bien que $rootScope.$broadcast independientemente de la relación entre el controlador de transmisión y el de recepción. De esa forma, el evento permanece dentro del conjunto de $rootScope.$$listeners mientras que con $rootScope.$broadcast el evento se propaga a todos los ámbitos de los niños, la mayoría de los cuales probablemente no sean oyentes de ese evento de todos modos. Y, por supuesto, en el extremo del controlador de recepción que acaba de utilizar $rootScope.$on.

Para esta opción, debe recordar destruir los oyentes rootScope del controlador:

var unbindEventHandler = $rootScope.$on('myEvent', myHandler);
$scope.$on('$destroy', function () {
  unbindEventHandler();
});

140
2018-04-06 19:34



¿Cómo puedo enviar mi objeto $ scope de un controlador a otro utilizando los métodos $ emit y. $ On?

Puede enviar cualquier objeto que desee dentro de la jerarquía de su aplicación, incluidos $ scope.

Aquí hay una idea rápida sobre cómo emisión y emitir trabajo.

Observe los nodos a continuación; todo anidado dentro del nodo 3. Usas emisión y emitir cuando tienes este escenario

Nota: El número de cada nodo en este ejemplo es arbitrario; podría ser fácilmente el número uno; el número dos; o incluso el número 1,348. Cada número es solo un identificador para este ejemplo. El objetivo de este ejemplo es mostrar la anidación de controladores / directivas angulares.

                 3
           ------------
           |          |
         -----     ------
         1   |     2    |
      ---   ---   ---  ---
      | |   | |   | |  | |

Mira este árbol. ¿Cómo respondes las siguientes preguntas?

Nota: Hay otras maneras de responder estas preguntas, pero aquí discutiremos emisión y emitir. Además, al leer a continuación el texto, suponga que cada número tiene su propio archivo (directiva, controlador) e.x. one.js, two.js, three.js

¿Cómo funciona el nodo 1 hablar al nodo 3?

En archivo one.js

scope.$emit('messageOne', someValue(s));

En archivo three.js - el nodo superior para todos los nodos hijos necesarios para comunicarse.

scope.$on('messageOne', someValue(s));

¿Cómo habla el nodo 2 al nodo 3?

En archivo two.js

scope.$emit('messageTwo', someValue(s));

En archivo three.js - el nodo superior para todos los nodos hijos necesarios para comunicarse.

scope.$on('messageTwo', someValue(s));

¿Cómo habla el nodo 3 al nodo 1 y / o al nodo 2?

En archivo three.js - el nodo superior para todos los nodos hijos necesarios para comunicarse.

scope.$broadcast('messageThree', someValue(s));

En archivo one.js && two.js cualquiera que sea el archivo que desee captar el mensaje o ambos.

scope.$on('messageThree', someValue(s));

¿Cómo habla el nodo 2 al nodo 1?

En archivo two.js

scope.$emit('messageTwo', someValue(s));

En archivo three.js - el nodo superior para todos los nodos hijos necesarios para comunicarse.

scope.$on('messageTwo', function( event, data ){
  scope.$broadcast( 'messageTwo', data );
});

En archivo one.js

scope.$on('messageTwo', someValue(s));

SIN EMBARGO

Cuando tenga todos estos nodos secundarios anidados tratando de comunicarse de esta manera, verá rápidamente muchos $ on's, $ broadcasty $ emiten.

Esto es lo que me gusta hacer.

En el NODO DE PADRES superior ( 3 en este caso ...), que puede ser su controlador principal ...

Entonces, en el archivo three.js

scope.$on('pushChangesToAllNodes', function( event, message ){
  scope.$broadcast( message.name, message.data );
});

Ahora en cualquiera de los nodos secundarios solo necesita $ emitir el mensaje o atraparlo usando $ en.

NOTA: En general, es bastante fácil cruzar la conversación en una ruta anidada sin usar $ emitir, $ emisión, o $ en, lo que significa que la mayoría de los casos de uso son para cuando intentas obtener un nodo 1 para comunicarse con el nodo 2 o viceversa.

¿Cómo habla el nodo 2 al nodo 1?

En archivo two.js

scope.$emit('pushChangesToAllNodes', sendNewChanges());

function sendNewChanges(){ // for some event.
  return { name: 'talkToOne', data: [1,2,3] };
}

En archivo three.js - el nodo superior para todos los nodos hijos necesarios para comunicarse.

Ya lo manejamos, ¿recuerdas?

En archivo one.js

scope.$on('talkToOne', function( event, arrayOfNumbers ){
  arrayOfNumbers.forEach(function(number){
    console.log(number);
  });
});

Todavía necesitarás usar $ en con cada valor específico que desea capturar, pero ahora puede crear lo que desee en cualquiera de los nodos sin tener que preocuparse por cómo transmitir el mensaje a través del espacio del nodo padre a medida que capturamos y transmitimos el genérico pushChangesToAllNodes.

Espero que esto ayude...


107
2017-07-11 14:47



Mandar $scope object de un controlador a otro, voy a discutir sobre $rootScope.$broadcast y $rootScope.$emit aquí como se usan más.

Caso 1:

$ rootScope. $ broadcast: -

$rootScope.$broadcast('myEvent',$scope.data);//Here `myEvent` is event name

$rootScope.$on('myEvent', function(event, data) {} //listener on `myEvent` event

$rootScope oyente no se destruyen automáticamente. Tienes que destruirlo usando $destroy. Es mejor usar $scope.$on como oyentes en $scope se destruyen automáticamente, es decir, tan pronto como se destruye $ scope.

$scope.$on('myEvent', function(event, data) {}

O,

  var customeEventListener = $rootScope.$on('myEvent', function(event, data) {

  }
  $scope.$on('$destroy', function() {
        customeEventListener();
  });

Caso 2 

$ rootScope. $ emit:

   $rootScope.$emit('myEvent',$scope.data);

   $rootScope.$on('myEvent', function(event, data) {}//$scope.$on not works

La principal diferencia en $ emitir y $ broadcast es que $ rootScope. $ Emitir evento debe ser escuchado usando $ rootScope. $ On, porque el evento emitido nunca se ve a través del árbol de alcance..
En este caso también debe destruir al oyente como en el caso de $ broadcast.

Editar:

Prefiero no usar $rootScope.$broadcast + $scope.$on pero usa    $rootScope.$emit+ $rootScope.$on. los $rootScope.$broadcast + $scope.$on combo puede causar serios problemas de rendimiento. Es decir   porque el evento burbujeará a través de todos los ámbitos.

Editar 2:

El problema tratado en esta respuesta se ha resuelto en angular.js   versión 1.2.7. $ broadcast ahora evita burbujeo sobre ámbitos no registrados   y funciona tan rápido como $ emitir.


35
2018-04-02 18:54



Debe usar $ rootScope para enviar y capturar eventos entre los controladores en la misma aplicación. Inyecta la dependencia $ rootScope en tus controladores. Aquí hay un ejemplo de trabajo.

app.controller('firstCtrl', function($scope, $rootScope) {        
        function firstCtrl($scope) {
        {
            $rootScope.$emit('someEvent', [1,2,3]);
        }
}

app.controller('secondCtrl', function($scope, $rootScope) {
        function secondCtrl($scope)
        {
            $rootScope.$on('someEvent', function(event, data) { console.log(data); });
        }
}

Los eventos vinculados al objeto $ scope solo funcionan en el controlador del propietario. La comunicación entre los controladores se realiza a través de $ rootScope o Servicios.


10
2018-01-10 07:01



Puede llamar a un servicio desde su controlador que devuelve una promesa y luego usarlo en su controlador. Y uso posterior $emit o $broadcast para informar a otros controladores al respecto. En mi caso, tuve que hacer llamadas http a través de mi servicio, así que hice algo como esto:

function ParentController($scope, testService) {
    testService.getList()
        .then(function(data) {
            $scope.list = testService.list;
        })
        .finally(function() {
            $scope.$emit('listFetched');
        })


    function ChildController($scope, testService) {
        $scope.$on('listFetched', function(event, data) {
            // use the data accordingly
        })
    }

y mi servicio se ve así

    app.service('testService', ['$http', function($http) {

        this.list = [];

        this.getList = function() {
            return $http.get(someUrl)
                .then(function(response) {
                    if (typeof response.data === 'object') {
                        list = response.data.results;

                        return response.data;
                    } else {
                        // invalid response
                        return $q.reject(response.data);
                    }

                }, function(response) {
                    // something went wrong
                    return $q.reject(response.data);
                });

        }

    }])

6
2018-03-20 11:19



Esta es mi función:

$rootScope.$emit('setTitle', newVal.full_name);

$rootScope.$on('setTitle', function(event, title) {
    if (scope.item) 
        scope.item.name = title;
    else 
        scope.item = {name: title};
});

3
2017-09-11 10:37



<!DOCTYPE html>
<html>

<head>
<script src= "http://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js"></script>
<script>
var app = angular.module('MyApp',[]);
app.controller('parentCtrl',function($scope){
  $scope.$on('MyEvent',function(event,data){    
    $scope.myData = data;
  });
 });

app.controller('childCtrl',function($scope){
  $scope.fireEvent = function(){ 
  $scope.$emit('MyEvent','Any Data');
  }  
 });
</script>
</head>
<body ng-app="MyApp">
<div ng-controller="parentCtrl" ng-model="myName">

{{myData}}

 <div ng-controller="childCtrl">
   <button ng-click="fireEvent()">Fire Event</button>
 </div>

</div>
</body>
</html>

3
2018-04-13 13:25



Terminé agregando una biblioteca EventEmitter externa para proyectar como un servicio e inyectándolo donde sea que lo necesite. Entonces puedo "emitir" y "encender" cualquier cosa en cualquier lugar sin preocuparme por la herencia del alcance. Es menos problemas de esta manera y sin duda un mejor rendimiento. También más legible para mí.

Apoyo Comodín: EventEmitter2

Buen rendimiento: eventemitter3

Otra alternativa: Goteo


2
2017-10-23 21:33