broadcast on y broadcast broadcast en angular


Tengo un footerController y un codeScannerController con diferentes vistas.

angular.module('myApp').controller('footerController', ["$scope", function($scope) {}]);

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

Cuando hago clic en un <li> en el pie de página.html Debería obtener este evento en codeScannerController.

<li class="button" ng-click="startScanner()">3</li>

Creo que se puede realizar con $on y $broadcast, pero no se cómo y no puedo encontrar ejemplos en ninguna parte.

Author: Gargaroz, 2013-10-18

4 answers

Si quieres $broadcast usar el $rootScope:

$scope.startScanner = function() {

    $rootScope.$broadcast('scanner-started');
}

Y luego para recibir, use el $scope de su controlador:

$scope.$on('scanner-started', function(event, args) {

    // do what you want to do
});

Si quieres puedes pasar argumentos cuando $broadcast:

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

Y luego recibirlos:

$scope.$on('scanner-started', function(event, args) {

    var anyThing = args.any;
    // do what you want to do
});

Documentación para esto dentro del ámbito docs.

 591
Author: Davin Tryon,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-07-23 14:11:42

Primero, una breve descripción de $on(), $broadcast() y $emit():

  • .$on(name, listener) - Escucha un evento específico de un name
  • .$broadcast(name, args) - Difundir un evento a través de $scope de todos los niños
  • .$emit(name, args) - Emitir un evento en la jerarquía $scope a todos los padres, incluyendo el $rootScope

Basado en el siguiente HTML (ver ejemplo completo aquí):

<div ng-controller="Controller1">
    <button ng-click="broadcast()">Broadcast 1</button>
    <button ng-click="emit()">Emit 1</button>
</div>

<div ng-controller="Controller2">
    <button ng-click="broadcast()">Broadcast 2</button>
    <button ng-click="emit()">Emit 2</button>
    <div ng-controller="Controller3">
        <button ng-click="broadcast()">Broadcast 3</button>
        <button ng-click="emit()">Emit 3</button>
        <br>
        <button ng-click="broadcastRoot()">Broadcast Root</button>
        <button ng-click="emitRoot()">Emit Root</button>
    </div>
</div>

Los eventos disparados atravesarán el $scopes como sigue:

  • Broadcast 1-Solo será visto por el Controlador 1 $scope
  • Emit 1-Será visto por el Controlador 1 $scope luego $rootScope
  • Broadcast 2-Será visto por el Controlador 2 $scope luego el Controlador 3 $scope
  • Emit 2-Será visto por el Controlador 2 $scope luego $rootScope
  • Broadcast 3 - Solo será visto por el Controlador 3 $scope
  • Emit 3-Será visto por el Controlador 3 $scope, Controlador 2 $scope luego $rootScope
  • Broadcast Root-Will ser visto por $rootScope y $scope de todos los Controladores (1, 2 luego 3)
  • Emit Root - Solo será visto por $rootScope

JavaScript para activar eventos (de nuevo, puede ver un ejemplo de trabajo aquí):

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');
    });
}]);
 84
Author: th3uiguy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-06-24 09:51:48

Una cosa que debe saber es pref prefix se refiere a un Método Angular, pref prefixes se refiere a métodos angulares que debe evitar usar.

A continuación se muestra una plantilla de ejemplo y sus controladores, exploraremos cómo broadcast broadcast/on on puede ayudarnos a lograr lo que queremos.

<div ng-controller="FirstCtrl">
    <input ng-model="name"/> 
    <button ng-click="register()">Register </button>
</div>

<div ng-controller="SecondCtrl">
    Registered Name: <input ng-model="name"/> 
</div>

Los controladores son

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

    }
});

app.controller('SecondCtrl', function($scope){

});

Mi pregunta es ¿cómo pasar el nombre al segundo controlador cuando un usuario hace clic en registrarse? Usted puede llegar a múltiples soluciones, pero la que vamos a utilizar está usando broadcast broadcast y on on.

$broadcast vs emit emit

¿Cuál debemos usar? broadcast broadcast canalizará a todos los elementos dom secundarios y emit emit canalizará la dirección opuesta a todos los elementos dom ancestros.

La mejor manera de evitar decidir entre emit emit o broadcast broadcast es canalizar desde el ro rootScope y usar broadcast broadcast a todos sus hijos. Lo que hace que nuestro caso sea mucho más fácil ya que nuestros elementos dom son hermanos.

Añadiendo ro rootScope y permite broadcast difusión

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

Tenga en cuenta que agregamos $rootScope y ahora estamos usando broadcast broadcast(broadcastName, arguments). Para broadcastName, queremos darle un nombre único para que podamos atrapar ese nombre en nuestra secondCtrl. He elegido BOOM! sólo por diversión. El segundo argumento 'argumentos' nos permite pasar valores a los oyentes.

Recibiendo nuestra emisión

En nuestro segundo controlador, necesitamos configurar el código para escuchar nuestra emisión

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

Es realmente así de simple. Ejemplo en vivo

Otras formas de lograr resultados similares

Trate de evitar el uso de este conjunto de métodos, ya que no es ni eficiente ni fácil de mantener, pero es una manera sencilla de solucionar los problemas que pueda tener.

Normalmente puedes hacer lo mismo usando un servicio o simplificando tus controladores. No discutiremos esto en detalle, pero pensé en mencionarlo para completar.

Por último, tenga en cuenta una transmisión realmente útil para escuchar es 'destroy destruir' de nuevo se puede ver el means significa que es un método u objeto creado por los códigos de proveedor. De todos modos destroy destroy se emite cuando se destruye un controlador, es posible que desee escuchar esto para saber cuándo se elimina su controlador.

 26
Author: Yang Li,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-03-01 23:58:19
//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();
       };
    }); }());
 1
Author: Sandy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-01-13 21:06:46