$ on e $ broadcast em angular

Eu tenho um footerController e codeScannerController com diferentes pontos de vista.

angular.module('myApp').controller('footerController', ["$scope", function($scope) {}]); angular.module('myApp').controller('codeScannerController', ["$scope", function($scope) { console.log("start"); $scope.startScanner = function(){... 

Quando clico em um

  • em footer.html, eu devo obter este evento em codeScannerController.

     
  • 3
  • Eu acho que pode ser realizado com $on e $broadcast , mas não sei como e não consigo encontrar exemplos em nenhum lugar.

    Se você quiser $broadcast use o $rootScope :

     $scope.startScanner = function() { $rootScope.$broadcast('scanner-started'); } 

    E, em seguida, para receber, use o $scope do seu controlador:

     $scope.$on('scanner-started', function(event, args) { // do what you want to do }); 

    Se você quiser, pode passar argumentos quando você $broadcast :

     $rootScope.$broadcast('scanner-started', { any: {} }); 

    E então receba-os:

     $scope.$on('scanner-started', function(event, args) { var anyThing = args.any; // do what you want to do }); 

    Documentação para isso dentro dos documentos do escopo .

  • Primeiro, uma breve descrição de $on() , $broadcast() e $emit() :

    • .$on(name, listener).$on(name, listener) um evento específico por um name
    • .$broadcast(name, args) – Transmite um evento pelo $scope de todas as crianças
    • .$emit(name, args) – Emite um evento na hierarquia $scope para todos os pais, incluindo o $rootScope

    Baseado no seguinte HTML (veja o exemplo completo aqui ):

     

    Os events triggersdos percorrerão os $scopes seguinte maneira:

    • Transmissão 1 – Só será visto pelo controlador 1 $scope
    • Emitem 1 – será visto pelo controlador 1 $scope e $rootScope
    • Broadcast 2 – será visto pelo controlador 2 $scope depois pelo Controller 3 $scope
    • Emit 2 – será visto pelo controlador 2 $scope e $rootScope
    • Broadcast 3 – Só será visto pelo Controller 3 $scope
    • Emit 3 – Será visto pelo Controller 3 $scope , Controller 2 $scope then $rootScope
    • Broadcast Root – Será visto por $rootScope e $scope de todos os Controllers (1, 2 e 3)
    • Emitir Root – só será visto por $rootScope

    JavaScript para acionar events (novamente, você pode ver um exemplo de trabalho aqui ):

     app.controller('Controller1', ['$scope', '$rootScope', function($scope, $rootScope){ $scope.broadcastAndEmit = function(){ // This will be seen by Controller 1 $scope and all children $scopes $scope.$broadcast('eventX', {data: '$scope.broadcast'}); // Because this event is fired as an emit (goes up) on the $rootScope, // only the $rootScope will see it $rootScope.$emit('eventX', {data: '$rootScope.emit'}); }; $scope.emit = function(){ // Controller 1 $scope, and all parent $scopes (including $rootScope) // will see this event $scope.$emit('eventX', {data: '$scope.emit'}); }; $scope.$on('eventX', function(ev, args){ console.log('eventX found on Controller1 $scope'); }); $rootScope.$on('eventX', function(ev, args){ console.log('eventX found on $rootScope'); }); }]); 

    Uma coisa que você deve saber é que o prefixo $ refere-se a um Método Angular, e os prefixos $$ referem-se a methods angulares que você deve evitar usar.

    abaixo está um modelo de exemplo e seus controladores, vamos explorar como $ broadcast / $ on pode nos ajudar a alcançar o que queremos.

     
    Registered Name:

    Os controladores são

     app.controller('FirstCtrl', function($scope){ $scope.register = function(){ } }); app.controller('SecondCtrl', function($scope){ }); 

    Minha pergunta para você é como você passa o nome para o segundo controlador quando um usuário clica em registrar? Você pode encontrar várias soluções, mas a que vamos usar está usando $ broadcast e $ on.

    $ broadcast vs $ emit

    Qual devemos usar? $ broadcast irá canalizar para todos os elementos filhos e $ emit irá canalizar a direção oposta para todos os elementos ancestors dom.

    A melhor maneira de evitar a decisão entre $ emit ou $ broadcast é canalizar a partir do $ rootScope e usar $ broadcast para todos os seus filhos. O que torna nosso caso muito mais fácil, já que nossos elementos são irmãos.

    Adicionando $ rootScope e permite $ broadcast

     app.controller('FirstCtrl', function($rootScope, $scope){ $scope.register = function(){ $rootScope.$broadcast('BOOM!', $scope.name) } }); 

    Note que adicionamos $ rootScope e agora estamos usando $ broadcast (broadcastName, arguments). Para broadcastName, queremos dar um nome exclusivo para que possamos capturar esse nome em nosso secondCtrl. Eu escolhi o BOOM! apenas por diversão. O segundo argumento ‘argumentos’ nos permite passar valores para os ouvintes.

    Recebendo nossa transmissão

    Em nosso segundo controlador, precisamos configurar o código para ouvir nossa transmissão

     app.controller('SecondCtrl', function($scope){ $scope.$on('BOOM!', function(events, args){ console.log(args); $scope.name = args; //now we've registered! }) }); 

    É tão simples assim. Exemplo Vivo

    Outras maneiras de alcançar resultados semelhantes

    Tente evitar usar este conjunto de methods, pois ele não é eficiente nem fácil de manter, mas é uma maneira simples de corrigir problemas que você possa ter.

    Você geralmente pode fazer a mesma coisa usando um serviço ou simplificando seus controladores. Nós não vamos discutir isso em detalhes, mas eu pensei em mencioná-lo por completo.

    Por último, tenha em mente que uma transmissão realmente útil para ouvir é ‘$ destroy’ novamente, você pode ver que $ significa que é um método ou object criado pelos códigos do fornecedor. De qualquer forma $ destroy é transmitido quando um controlador é destruído, você pode querer ouvir isso para saber quando seu controlador é removido.

     //Your broadcast in service (function () { angular.module('appModule').factory('AppService', function ($rootScope, $timeout) { function refreshData() { $timeout(function() { $rootScope.$broadcast('refreshData'); }, 0, true); } return { RefreshData: refreshData }; }); }()); //Controller Implementation (function () { angular.module('appModule').controller('AppController', function ($rootScope, $scope, $timeout, AppService) { //Removes Listeners before adding them //This line will solve the problem for multiple broadcast call $scope.$$listeners['refreshData'] = []; $scope.$on('refreshData', function() { $scope.showData(); }); $scope.onSaveDataComplete = function() { AppService.RefreshData(); }; }); }());