Travailler avec $champ d'application.$émettent $et la portée.$sur

Comment puis-je envoyer mon objet $scope d'un contrôleur à un autre en utilisant les méthodes .$emit et .$on ?

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

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

ça ne marche pas comme je le pense. Comment fonctionne $emit et $on ?

848
demandé sur Premraj 2013-01-24 17:03:17
la source

13 ответов

tout d'abord, la relation parent-enfant est importante. Vous avez deux possibilités pour émettre un événement:

  • $broadcast -- expédie l'événement vers le bas à tous les scopes d'enfant,
  • $emit -- distribue l'événement vers le haut à travers le champ d'application de la hiérarchie.

Je ne sais rien de votre relation de contrôleurs (portées), mais il y a plusieurs options:

  1. si le champ d'application de firstCtrl est parent du champ d'application de secondCtrl , votre code devrait travailler en remplaçant $emit par $broadcast dans firstCtrl :

    function firstCtrl($scope)
    {
        $scope.$broadcast('someEvent', [1,2,3]);
    }
    
    function secondCtrl($scope)
    {
        $scope.$on('someEvent', function(event, mass) { console.log(mass); });
    }
    
  2. dans le cas où il n'y a pas de relation parent-enfant entre vos portées vous peut injecter $rootScope dans le contrôleur et diffuser l'événement à tous les scopes d'enfant (c'est-à-dire aussi secondCtrl ).

    function firstCtrl($rootScope)
    {
        $rootScope.$broadcast('someEvent', [1,2,3]);
    }
    
  3. enfin, quand vous avez besoin d'envoyer l'événement à partir du contrôleur enfant pour les portées vers le haut, vous pouvez utiliser $scope.$emit . Si le champ d'application de firstCtrl est parent du champ d'application de secondCtrl :

    function firstCtrl($scope)
    {
        $scope.$on('someEvent', function(event, data) { console.log(data); });
    }
    
    function secondCtrl($scope)
    {
        $scope.$emit('someEvent', [1,2,3]);
    }
    
1474
répondu zbynour 2014-12-08 12:55:53
la source

je suggérerais en outre une 4ème option comme meilleure alternative aux options proposées par @zbynour.

utiliser $rootScope.$emit plutôt que $rootScope.$broadcast quelle que soit la relation entre le traceur et le contrôleur récepteur. De cette façon, l'événement reste dans l'ensemble de $rootScope.$$listeners alors qu'avec $rootScope.$broadcast l'événement se propage à tous les enfants scopes, dont la plupart ne seront probablement pas auditeurs de cet événement de toute façon. Et bien sûr dans la réception fin du controller il suffit d'utiliser $rootScope.$on .

pour cette option vous devez vous rappeler de détruire les écouteurs rootScope du contrôleur:

var unbindEventHandler = $rootScope.$on('myEvent', myHandler);
$scope.$on('$destroy', function () {
  unbindEventHandler();
});
140
répondu Thalis K. 2017-04-09 14:58:15
la source

Comment puis-je envoyer mon objet $scope d'un controller à un autre en utilisant .$émettent et .$sur les méthodes?

vous pouvez envoyer n'importe quel objet que vous voulez dans la hiérarchie de votre application, y compris $scope .

Voici une idée rapide sur la façon dont diffuser et émettre travailler.

remarquez les noeuds ci-dessous; tous imbriqués le nœud 3. Vous utilisez broadcast et emit lorsque vous avez ce scénario.

Note: le nombre de chaque noeud dans cet exemple est arbitraire; il pourrait facilement être le nombre UN; le nombre deux; ou même le nombre 1,348. Chaque numéro n'est qu'un identificateur pour cet exemple. Le but de cet exemple est de montrer l'imbrication Angulaire contrôleurs/directives.

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

contrôle cet arbre. Comment pouvez-vous répondre aux questions suivantes?

Note: il y a d'autres façons de répondre à ces questions, mais nous allons discuter ici émission et émission . De plus, en lisant le texte ci-dessous, supposez que chaque numéro possède son propre fichier (directive, contrôleur) E. x. un seul.js, deux.js, trois.js.

Comment nœud 1 parler à nœud 3 ?

Dans le fichier .js

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

dans le dossier trois.js - le noeud supérieur à tous les noeuds enfants nécessaires pour communiquer.

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

comment le noeud 2 parle-t-il au noeud 3?

Dans le fichier les deux.js

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

dans le dossier trois.js - le plus haut noeud à tous les noeuds enfants nécessaires pour communiquer.

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

comment le noeud 3 s'adresse-t-il au noeud 1 et/ou au noeud 2?

dans le dossier trois.js - le noeud supérieur à tous les noeuds enfants nécessaires pour communiquer.

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

Dans le fichier .js && les deux.js n'importe quel fichier vous voulez attraper le message ou les deux.

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

comment le noeud 2 parle-t-il au noeud 1?

Dans le fichier les deux.js

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

dans le dossier trois.js - le noeud supérieur à tous les noeuds enfants nécessaires pour communiquer.

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

Dans le fichier .js

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

toutefois

quand vous avez tous ces noeuds enfant imbriqués essayer de communiquer comme ceci, vous verrez rapidement beaucoup de $on , $broadcast , et $emit .

voici ce que j'aime faire.

dans le noeud PARENT supérieur ( 3 dans ce cas... ), qui peut être votre contrôleur parent...

donc, dans le dossier trois.js

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

maintenant dans l'un des noeuds enfant, vous avez seulement besoin de $emit le message ou l'attraper en utilisant $sur .

NOTE: il est normalement assez facile de croiser une conversation dans un chemin imbriqué sans utiliser $emit , $broadcast , ou $on , ce qui signifie que la plupart des cas d'utilisation sont pour quand vous êtes essayer d'obtenir le noeud 1 pour communiquer avec le noeud 2 ou vice versa.

comment le noeud 2 parle-t-il au noeud 1?

Dans le fichier les deux.js

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

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

dans le dossier trois.js - le noeud supérieur à tous les noeuds enfants nécessaires pour communiquer.

on s'est déjà occupé de celui-ci, tu te souviens?

Dans le fichier .js

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

vous aurez toujours besoin d'utiliser $sur avec chaque valeur spécifique que vous voulez attraper, mais maintenant vous pouvez créer tout ce que vous voulez dans l'un des noeuds sans avoir à vous soucier de la façon d'obtenir le message à travers l'écart de noeud parent que nous attrapons et de diffuser le générique pushChangesToAllNodes .

Espérons que cette aide...

108
répondu SoEzPz 2016-01-13 19:59:02
la source

pour envoyer $scope object d'un contrôleur à l'autre, je vais parler de $rootScope.$broadcast et $rootScope.$emit ici comme ils sont le plus utilisés.

Cas 1 :

$ rootScope.$ diffusion: -

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

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

$rootScope ne sont pas détruits automatiquement. Vous devez le détruire en utilisant $destroy . Il est préférable d'utiliser $scope.$on comme auditeurs sur $scope sont détruits automatiquement, c'est à dire dès que $champ d'application est détruit.

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

Ou,

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

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

Cas 2:

$ rootScope.$emit:

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

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

la principale différence entre $emit et $broadcast est $rootScope.$emit event doit être écouté en utilisant $rootScope.$on, parce que l'événement émis ne descend jamais à travers l'arbre de visée. .

Dans ce cas aussi, vous devez détruire l'auditeur comme dans le cas de $de diffusion.

Modifier:

je préfère ne pas utiliser $rootScope.$broadcast + $scope.$on mais utiliser $rootScope.$emit+ $rootScope.$on . Le combo $rootScope.$broadcast + $scope.$on peut causer de graves problèmes de performance. C'est parce que l'événement va déborder à travers tous les horizons.

Edit 2 :

la question abordée dans la présente réponse a été résolue en angle.js la version 1.2.7. $diffuser maintenant évite de déborder non étendues et fonctionne aussi vite que $émettent.

37
répondu Ved 2017-12-07 10:27:23
la source

vous devez utiliser $rootScope pour envoyer et capturer des événements entre contrôleurs dans la même application. Injectez $rootScope à vos controllers. Voici un exemple de travail.

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

les événements liés à l'objet $ scope ne fonctionnent que dans le contrôleur propriétaire. La Communication entre les contrôleurs se fait via $rootScope ou des Services.

10
répondu kyasar 2017-06-14 09:23:43
la source

vous pouvez appeler un service de votre contrôleur qui renvoie une promesse et l'utiliser ensuite dans votre contrôleur. Et utilisez $emit ou $broadcast pour en informer les autres contrôleurs. Dans mon cas, j'ai dû faire des appels http via mon service, donc j'ai fait quelque chose comme ça:

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

et mon service ressemble à ceci

    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
répondu ribhu 2018-03-17 05:28:43
la source

C'est ma fonction:

$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
répondu trai bui 2014-10-07 00:23:11
la source
<!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
répondu Prashant_M 2015-04-13 16:25:38
la source

j'ai fini par ajouter une bibliothèque D'EventEmitter externe à projeter comme un service et l'injecter partout où j'ai besoin. Donc je peux "émettre" et " sur " n'importe quoi n'importe où sans m'occuper de l'héritage de scope. C'est moins de problèmes de cette façon et certainement de meilleures performances. Aussi plus lisible pour moi.

soutien Joker: EventEmitter2

Good performance: eventemitter3

autres alternative: goutte à Goutte

3
répondu Mustafa Dokumacı 2015-10-24 00:33:17
la source

le code ci-dessous indique les deux sous-contrôleurs d'où les événements sont envoyés vers le haut au contrôleur parent (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/

2
répondu Shushanth Pallegar 2018-03-17 05:17:31
la source

Scope (s) peut être utilisé pour propager, envoyer l'événement aux enfants scope ou parent.

$emit - propage l'événement à parent. $émission - se propage à l'événement pour les enfants. $on - méthode pour écouter les événements, propagée par $emit et $broadcast.

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

exemple App.js :

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

ici vous pouvez tester le code: http://jsfiddle.net/zp6v0rut/41 /

1
répondu Vasyl Gutnyk 2017-03-22 17:59:56
la source

selon l'événement angularjs docs, l'extrémité de réception doit contenir des arguments avec une structure comme

@params

-- {Objet} événement qui a été l'objet d'événement contenant des infos sur l'événement

-- {Objet} args qui sont passés par le destinataire de l'appel (à Noter que ce ne peut être qu'une donc préférable d'envoyer un objet dictionary toujours)

$scope.$on('fooEvent', function (event, args) { console.log(args) }); De votre code

Also si vous essayez d'obtenir un élément d'information partagé pour être disponible à travers différents contrôleurs, il y a une autre façon d'y parvenir et c'est les services angulaires.Comme les services sont des singletons, les informations peuvent être stockées et récupérées à travers les contrôleurs.Il suffit de créer des fonctions getter et setter dans ce service, exposer ces fonctions, faire des variables globales dans le service et les utiliser pour stocker l'information

0
répondu Wajih Siddiqui 2017-04-09 19:04:20
la source

la voie la plus facile:

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>
0
répondu Sangwin Gawande 2017-06-19 12:31:06
la source

Autres questions sur javascript angularjs