example eventos event javascript angularjs

javascript - eventos - rootscope watch



Trabajar con $ scope. $ Emit y $ scope. $ En (13)

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

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. ¿Cómo funcionan $emit y $on trabajo?


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

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

Aquí hay una idea rápida de cómo funcionan la emisión y la emisión .

Note los nodos abajo; todos anidados dentro del nodo 3. Usted usa transmisión y emisión cuando tiene este escenario.

Nota: El número de cada nodo en este ejemplo es arbitrario; fácilmente podría ser 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 punto de este ejemplo es mostrar el anidamiento de los controladores / directivas angulares.

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

Echa un vistazo a este árbol. ¿Cómo respondes las siguientes preguntas?

Nota: Hay otras formas de responder a estas preguntas, pero aquí hablaremos sobre transmisión y emisión . Además, cuando lea el texto debajo, suponga que cada número tiene su propio archivo (directiva, controlador) ex one.js, two.js, three.js.

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

En el archivo one.js

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

En el archivo three.js : el nodo superior a todos los nodos secundarios necesarios para la comunicación.

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

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

En el archivo two.js

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

En el archivo three.js : el nodo superior a todos los nodos secundarios necesarios para la comunicación.

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

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

En el archivo three.js : el nodo superior a todos los nodos secundarios necesarios para la comunicación.

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

En el archivo one.js && two.js, el archivo que desee capturar el mensaje o ambos.

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

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

En el archivo two.js

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

En el archivo three.js : el nodo superior a todos los nodos secundarios necesarios para la comunicación.

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

En el archivo one.js

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

SIN EMBARGO

Cuando tenga todos estos nodos secundarios anidados intentando comunicarse de esta manera, verá rápidamente muchos $ on''s , $ broadcast''s y $ emit''s .

Esto es lo que me gusta hacer.

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

Así, 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 capturarlo usando $ on .

NOTA: normalmente es bastante fácil realizar una conversación cruzada en una ruta anidada sin usar $ emit , $ broadcast o $ on , lo que significa que la mayoría de los casos de uso son para cuando intenta que el nodo 1 se comunique con el nodo 2 o viceversa.

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

En el archivo two.js

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

En el archivo three.js : el nodo superior a todos los nodos secundarios necesarios para la comunicación.

Ya manejamos esto, ¿recuerdas?

En el archivo one.js

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

Aún necesitará usar $ on con cada valor específico que desee capturar, pero ahora puede crear lo que quiera en cualquiera de los nodos sin tener que preocuparse sobre cómo hacer llegar el mensaje a través del espacio del nodo principal a medida que detectamos y transmitimos Los pushChangesToAllNodes genéricos.

Espero que esto ayude...


De acuerdo con los documentos del evento angularjs, el extremo receptor debe contener argumentos con una estructura como

@params

- El evento {Object} es el objeto de evento que contiene información sobre el evento.

- {Objetos} argumentos que son pasados ​​por el llamado (Tenga en cuenta que esto solo puede ser uno por lo que es mejor enviar siempre un objeto de diccionario)

$scope.$on(''fooEvent'', function (event, args) { console.log(args) }); Desde tu codigo

Además, si está tratando de obtener una información compartida para que esté disponible a través de diferentes controladores, existe otra forma de lograrlo, y es servicios angulares. Dado que los servicios son singletons, la información se puede almacenar y buscar entre los controladores. Simplemente cree y obtenga Las funciones de establecimiento en ese servicio, exponen estas funciones, crean variables globales en el servicio y las utilizan para almacenar la información.


Debe usar $ rootScope para enviar y capturar eventos entre controladores en la misma aplicación. Inyecte la dependencia de $ rootScope a sus 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 propietario. La comunicación entre los controladores se realiza a través de $ rootScope o Servicios.


El (los) alcance (s) se puede usar para propagar, enviar un evento al alcance hijo o padre.

$ emit - propaga el evento al padre. $ broadcast - propaga el evento a los niños. $ on - método para escuchar los eventos, propagado por $ emit y $ broadcast.

ejemplo index.html :

<div ng-app="appExample" ng-controller="EventCtrl"> Root(Parent) scope count: {{count}} <div> <button ng-click="$emit(''MyEvent'')">$emit(''MyEvent'')</button> <button ng-click="$broadcast(''MyEvent'')">$broadcast(''MyEvent'')</button><br> Childrent scope count: {{count}} </div> </div>

ejemplo app.js :

angular.module(''appExample'', []) .controller(''EventCtrl'', [''$scope'', function($scope) { $scope.count = 0; $scope.$on(''MyEvent'', function() { $scope.count++; }); }]);

Aquí puede probar el código: http://jsfiddle.net/zp6v0rut/41/


El siguiente código muestra los dos sub-controladores desde donde los eventos se envían hacia arriba al controlador principal (rootScope)

<body ng-app="App"> <div ng-controller="parentCtrl"> <p>City : {{city}} </p> <p> Address : {{address}} </p> <div ng-controller="subCtrlOne"> <input type="text" ng-model="city" /> <button ng-click="getCity(city)">City !!!</button> </div> <div ng-controller="subCtrlTwo"> <input type="text" ng-model="address" /> <button ng-click="getAddrress(address)">Address !!!</button> </div> </div> </body>

var App = angular.module(''App'', []); // parent controller App.controller(''parentCtrl'', parentCtrl); parentCtrl.$inject = ["$scope"]; function parentCtrl($scope) { $scope.$on(''cityBoom'', function(events, data) { $scope.city = data; }); $scope.$on(''addrBoom'', function(events, data) { $scope.address = data; }); } // sub controller one App.controller(''subCtrlOne'', subCtrlOne); subCtrlOne.$inject = [''$scope'']; function subCtrlOne($scope) { $scope.getCity = function(city) { $scope.$emit(''cityBoom'', city); } } // sub controller two App.controller(''subCtrlTwo'', subCtrlTwo); subCtrlTwo.$inject = ["$scope"]; function subCtrlTwo($scope) { $scope.getAddrress = function(addr) { $scope.$emit(''addrBoom'', addr); } }

http://jsfiddle.net/shushanthp/zp6v0rut/


En primer lugar, la relación de alcance padre-hijo sí importa. Tienes dos posibilidades para emitir algún evento:

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

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

  1. Si el ámbito de firstCtrl es el padre del ámbito de secondCtrl , su código debería funcionar reemplazando $emit firstCtrl 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 sus ámbitos, puede inyectar $rootScope en el controlador y transmitir el evento a todos los ámbitos secundarios (es decir, también secondCtrl ).

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

  3. Finalmente, cuando necesite enviar el evento desde el controlador secundario a los ámbitos ascendentes, puede usar $scope.$emit . Si el ámbito de firstCtrl es el padre del ámbito de secondCtrl :

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


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}; });


La forma más fácil :

HTML

<div ng-app="myApp" ng-controller="myCtrl"> <button ng-click="sendData();"> Send Data </button> </div>

JavaScript

<script> var app = angular.module(''myApp'', []); app.controller(''myCtrl'', function($scope, $rootScope) { function sendData($scope) { var arrayData = [''sam'',''rumona'',''cubby'']; $rootScope.$emit(''someEvent'', arrayData); } }); app.controller(''yourCtrl'', function($scope, $rootScope) { $rootScope.$on(''someEvent'', function(event, data) { console.log(data); }); }); </script>


Para enviar el $scope object de un controlador a otro, discutiré sobre $rootScope.$broadcast y $rootScope.$emit aquí, ya que se utilizan 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 $rootScope no se destruye automáticamente. Necesitas destruirlo usando $destroy . Es mejor usar $scope.$on On, ya que los 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 $ emit y $ broadcast es que el evento $ rootScope. $ Emit debe escucharse con $ rootScope. $ On, porque el evento emitido nunca se reduce a través del árbol de alcance. .
En este caso también debes destruir al oyente como en el caso de $ broadcast.

Editar:

Prefiero no usar $rootScope.$broadcast + $scope.$on $rootScope.$emit+ $rootScope.$on pero uso $rootScope.$emit+ $rootScope.$on . El $rootScope.$broadcast + $scope.$on combo puede causar serios problemas de rendimiento. Eso es porque el evento se derrumbará a través de todos los ámbitos.

Edición 2 :

El problema tratado en esta respuesta se resolvió en angular.js versión 1.2.7. $ broadcast ahora evita las burbujas en los ámbitos no registrados y se ejecuta tan rápido como $ emit.


Puede llamar a un servicio desde su controlador que devuelve una promesa y luego utilizarlo en su controlador. Y además use $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 asi

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); }); } }])


También sugeriría una cuarta opción como una mejor alternativa a las opciones propuestas por @zbynour.

Use $rootScope.$emit lugar de $rootScope.$broadcast independientemente de la relación entre el transmisor y el controlador receptor. De esa manera, el evento permanece dentro del conjunto de $rootScope.$$listeners mientras que con $rootScope.$broadcast el evento se propaga a todos los ámbitos secundarios, la mayoría de los cuales probablemente no serán escuchas de ese evento de todos modos. Y, por supuesto, en el extremo del controlador que recibe, simplemente usa $rootScope.$on .

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

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


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

Soporte de comodín: EventEmitter2

Buen rendimiento: eventemitter3

Otra alternativa: Drip


<!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>