javascript - example - broadcast angularjs



Trabalhando com $ scope. $ Emit e $ scope. $ On (9)

Como posso enviar meu objeto $scope de um controller para outro usando .$emit e .$on métodos?

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

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

Não funciona do jeito que eu acho que deveria. Como $emit e $on work?


Answer #1

Como posso enviar meu objeto $ scope de um controller para outro usando $ emit e $ em métodos?

Você pode enviar qualquer objeto que desejar na hierarquia do seu aplicativo, incluindo o escopo $ .

Aqui está uma idéia rápida sobre como a transmissão e a emissão funcionam.

Observe os nós abaixo; todos aninhados dentro do nó 3. Você usa broadcast e emite quando tem esse cenário.

Nota: O número de cada nó neste exemplo é arbitrário; poderia facilmente ser o número um; o número dois; ou até mesmo o número 1.348. Cada número é apenas um identificador para este exemplo. O objetivo deste exemplo é mostrar o aninhamento de controladores / diretivas angulares.

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

Confira esta árvore. Como você responde as seguintes perguntas?

Nota: Existem outras maneiras de responder a estas perguntas, mas aqui discutiremos broadcast e emit . Além disso, ao ler abaixo o texto, suponha que cada número tenha seu próprio arquivo (diretiva, controlador) ex one.js, two.js, three.js.

Como o nó 1 fala com o nó 3 ?

No arquivo one.js

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

No arquivo three.js - o nó mais alto para todos os nós filhos necessários para se comunicar.

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

Como o nó 2 fala com o nó 3?

No arquivo two.js

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

No arquivo three.js - o nó mais alto para todos os nós filhos necessários para se comunicar.

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

Como o nó 3 fala com o nó 1 e / ou o nó 2?

No arquivo three.js - o nó mais alto para todos os nós filhos necessários para se comunicar.

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

No arquivo one.js && two.js, qualquer arquivo que você queira capturar a mensagem ou ambos.

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

Como o nó 2 fala com o nó 1?

No arquivo two.js

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

No arquivo three.js - o nó mais alto para todos os nós filhos necessários para se comunicar.

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

No arquivo one.js

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

CONTUDO

Quando você tem todos esses nós filhos aninhados tentando se comunicar assim, você verá rapidamente muitos $ on's , $ broadcast's e $ emit's .

Aqui está o que eu gosto de fazer.

No mais alto PARENT NODE ( 3 neste caso ...), que pode ser seu controlador pai ...

Então, no arquivo three.js

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

Agora, em qualquer um dos nós filhos, você precisa apenas $ emitir a mensagem ou pegá-la usando $ on .

Observação: normalmente é muito fácil para cruzar conversa em um caminho aninhado sem usar $ emit , $ broadcast ou $ on , que significa que a maioria dos casos de uso são para quando você está tentando obter o nó 1 para se comunicar com o nó 2 ou vice-versa.

Como o nó 2 fala com o nó 1?

No arquivo two.js

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

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

No arquivo three.js - o nó mais alto para todos os nós filhos necessários para se comunicar.

Nós já lidamos com isso, lembra?

No arquivo one.js

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

Você ainda precisará usar $ on com cada valor específico que deseja capturar, mas agora pode criar o que quiser em qualquer um dos nós sem ter que se preocupar em como passar a mensagem através da lacuna do nó pai conforme captamos e transmitimos os pushChangesToAllNodes genéricos.

Espero que isto ajude...


Answer #2

A maneira mais 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>

Answer #3

Acabei adicionando uma biblioteca EventEmitter externa para projetar como um serviço e injetando-o onde quer que eu precise. Então eu posso "emitir" e "on" qualquer coisa em qualquer lugar sem se importar com herança de escopo. É menos problema dessa maneira e certamente melhor desempenho. Também mais legível para mim.

Suporte a curinga: EventEmitter2

Bom desempenho: eventemitter3

Outra alternativa: Drip


Answer #4

De acordo com os documentos do evento angularjs, o final receptor deve conter argumentos com uma estrutura como

@params

- Evento {Object} sendo o objeto de evento contendo informações sobre o evento

- {Object} argumentos que são passados ​​pelo chamado (Observe que isso pode ser apenas um, então é melhor enviar um objeto de dicionário sempre)

$scope.$on('fooEvent', function (event, args) { console.log(args) }); Do seu código

Além disso, se você está tentando obter uma informação compartilhada disponível em diferentes controladores, há uma outra maneira de conseguir isso, ou seja, os serviços angulares. Como os serviços são singletons, as informações podem ser armazenadas e buscadas nos controladores. setter funciona naquele serviço, exponha essas funções, faça variáveis ​​globais no serviço e use-as para armazenar as informações


Answer #5

Esta é minha função:

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

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

Answer #6

Eu sugeriria adicionalmente uma quarta opção como uma alternativa melhor às opções propostas por @zbynour.

Use $rootScope.$emit vez de $rootScope.$broadcast independente da relação entre o controlador de $rootScope.$broadcast e recepção. Dessa forma, o evento permanece dentro do conjunto de $rootScope.$$listeners enquanto que com $rootScope.$broadcast o evento se propaga para todos os escopos filhos, a maioria dos quais provavelmente não serão ouvintes daquele evento. E, claro, no final do controlador de recebimento, você só usa $rootScope.$on .

Para esta opção, você deve se lembrar de destruir os ouvintes rootScope do controlador:

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

Answer #7

Para enviar $scope object de um controlador para outro, eu discutirei sobre $rootScope.$broadcast e $rootScope.$emit aqui como eles são mais usados.

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 listener não são destruídos automaticamente. Você precisa destruí-lo usando $destroy . É melhor usar o $scope.$on que os ouvintes no $scope são destruídos automaticamente, ou seja, assim que o escopo $ é destruído.

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

Ou,

  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

A principal diferença em $ emit e $ broadcast é que $ rootScope. $ Emit event deve ser escutado usando $ rootScope. $ On, porque o evento emitido nunca desce através da árvore de escopo. .
Neste caso, você também deve destruir o ouvinte como no caso de $ broadcast.

Editar:

Eu prefiro não usar $rootScope.$broadcast + $scope.$on mas use $rootScope.$emit+ $rootScope.$on . O $rootScope.$broadcast + $scope.$on combo pode causar sérios problemas de desempenho. Isso ocorre porque o evento vai se espalhar por todos os escopos.

Editar 2 :

O problema abordado nesta resposta foi resolvido em angular.js versão 1.2.7. O $ broadcast agora evita borbulhar sobre escopos não registrados e é executado tão rápido quanto $ emitem.


Answer #8

Você deve usar o $ rootScope para enviar e capturar eventos entre os controladores no mesmo aplicativo. Injetar $ rootScope dependência para seus controladores. Aqui está um exemplo de trabalho.

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

Eventos vinculados ao objeto $ scope apenas funcionam no controlador proprietário. A comunicação entre controladores é feita via $ rootScope ou Services.


Answer #9
<!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>




angularjs