Comment puis-je envoyer mon objet $scope
d'un contrôleur à un autre à l'aide des 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); });
}
Cela ne fonctionne pas comme je le pense. Comment fonctionnent $emit
et $on
?
Tout d'abord, la relation de portée parent-enfant est importante. Vous avez deux possibilités pour émettre un événement:
$broadcast
- envoie l'événement vers le bas à toutes les portées enfant,$emit
- envoie l'événement par le haut dans la hiérarchie de la portée.Je ne sais rien de votre relation contrôleurs (scopes), mais il y a plusieurs options:
Si la portée de firstCtrl
est parent de la portée de secondCtrl
, votre code devrait fonctionner 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); });
}
Au cas où il n'y aurait pas de relation parent-enfant entre vos portées, vous pouvez injecter $rootScope
dans le contrôleur et diffuser l'événement à tous les portées enfants (c'est-à-dire aussi secondCtrl
).
function firstCtrl($rootScope)
{
$rootScope.$broadcast('someEvent', [1,2,3]);
}
Enfin, lorsque vous avez besoin d'envoyer l'événement du contrôleur enfant vers le haut, vous pouvez utiliser $scope.$emit
. Si la portée de firstCtrl
est le parent de la portée secondCtrl
:
function firstCtrl($scope)
{
$scope.$on('someEvent', function(event, data) { console.log(data); });
}
function secondCtrl($scope)
{
$scope.$emit('someEvent', [1,2,3]);
}
Je suggérerais en outre une quatrième option comme meilleure alternative aux options proposées par @zbynour.
Utilisez $rootScope.$emit
plutôt que $rootScope.$broadcast
quelle que soit la relation entre le contrôleur de transfert et de réception. De cette façon, l'événement reste dans l'ensemble de $rootScope.$$listeners
alors que avec $rootScope.$broadcast
l'événement se propage à tous les portées des enfants, dont la plupart ne seront probablement pas à l'écoute de toute façon. Et bien sûr, du côté du contrôleur récepteur, vous utilisez simplement $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();
});
Comment puis-je envoyer mon objet $ scope d'un contrôleur à un autre avec les méthodes. $ Emit et. $ On?
Vous pouvez envoyer n’importe quel objet de votre choix dans la hiérarchie de votre application, y compris $ scope.
Voici une rapide idée sur le fonctionnement de broadcast et emit.
Notez les nœuds ci-dessous; tous sont imbriqués dans le noeud 3. Vous utilisez diffusion et émission lorsque vous avez ce scénario.
Remarque: Le numéro de chaque nœud dans cet exemple est arbitraire; ça pourrait facilement être le numéro un; le numéro deux; ou même le nombre 1.348. Chaque numéro est juste un identifiant pour cet exemple. Le but de cet exemple est de montrer l'imbrication de contrôleurs/directives Angular.
3
------------
| |
----- ------
1 | 2 |
--- --- --- ---
| | | | | | | |
Découvrez cet arbre. Comment répondez-vous aux questions suivantes?
Remarque: Il existe d'autres moyens de répondre à ces questions, mais ici, nous discuterons de diffusion et émission. En outre, lors de la lecture du texte ci-dessous, supposons que chaque numéro a son propre fichier (directive, contrôleur) e.x. un.js, deux.js, trois.js.
Comment le noeud 1 parle-t-il au noeud ?
Dans le fichier one.js
scope.$emit('messageOne', someValue(s));
Dans le fichier three.js - le nœud le plus haut pour tous les nœuds enfants nécessaires à la communication.
scope.$on('messageOne', someValue(s));
Comment le noeud 2 parle-t-il au noeud 3?
Dans le fichier two.js
scope.$emit('messageTwo', someValue(s));
Dans le fichier three.js - le nœud le plus haut pour tous les nœuds enfants nécessaires à la communication.
scope.$on('messageTwo', someValue(s));
Comment le noeud 3 parle-t-il au noeud 1 et/ou au noeud 2?
Dans le fichier three.js - le nœud le plus haut pour tous les nœuds enfants nécessaires à la communication.
scope.$broadcast('messageThree', someValue(s));
Dans le fichier one.js && two.js le fichier dans lequel vous voulez intercepter le message ou les deux.
scope.$on('messageThree', someValue(s));
Comment le noeud 2 parle-t-il au noeud 1?
Dans le fichier two.js
scope.$emit('messageTwo', someValue(s));
Dans le fichier three.js - le nœud le plus haut pour tous les nœuds enfants nécessaires à la communication.
scope.$on('messageTwo', function( event, data ){
scope.$broadcast( 'messageTwo', data );
});
Dans le fichier one.js
scope.$on('messageTwo', someValue(s));
CEPENDANT
Lorsque vous avez tous ces nœuds enfants imbriqués qui tentent de communiquer de cette façon, vous verrez rapidement plusieurs $ on's, $ broadcast's et $ emit's.
Voici ce que j'aime faire.
Dans le nœud parent le plus élevé ( dans ce cas ...), qui peut être votre contrôleur parent ...
Donc, dans le fichier three.js
scope.$on('pushChangesToAllNodes', function( event, message ){
scope.$broadcast( message.name, message.data );
});
Maintenant, dans n'importe lequel des nœuds enfants, il vous suffit de $ emit le message ou de l'attraper à l'aide de $ on.
NOTE: Il est normalement assez facile de passer d’un dialogue à l’autre dans un chemin imbriqué sans utiliser $ emit, $ broadcast ou $ on, ce qui signifie que la plupart des cas d’utilisation sont destinés à la communication du noeud 1 avec le noeud 2 ou vice-versa.
Comment le noeud 2 parle-t-il au noeud 1?
Dans le fichier two.js
scope.$emit('pushChangesToAllNodes', sendNewChanges());
function sendNewChanges(){ // for some event.
return { name: 'talkToOne', data: [1,2,3] };
}
Dans le fichier three.js - le nœud le plus haut pour tous les nœuds enfants nécessaires à la communication.
Nous avons déjà traité celui-là
Dans le fichier one.js
scope.$on('talkToOne', function( event, arrayOfNumbers ){
arrayOfNumbers.forEach(function(number){
console.log(number);
});
});
Vous aurez toujours besoin d'utiliser $ on avec chaque valeur spécifique que vous voulez intercepter, mais vous pouvez maintenant créer ce que vous voulez dans n'importe quel nœud sans avoir à vous soucier de la façon de transmettre le message au parent. intervalle de nœud lorsque nous attrapons et diffusons le générique pushChangesToAllNodes.
J'espère que cela t'aides...
Pour envoyer $scope object
d'un contrôleur à un autre, je discuterai de $rootScope.$broadcast
et de $rootScope.$emit
ici car ils sont le plus utilisés.
Cas 1:
$ rootScope. $ broadcast: -
$rootScope.$broadcast('myEvent',$scope.data);//Here `myEvent` is event name
$rootScope.$on('myEvent', function(event, data) {} //listener on `myEvent` event
$rootScope
auditeur ne sont pas détruits automatiquement. Vous devez le détruire en utilisant $destroy
. Il est préférable d’utiliser $scope.$on
car les écouteurs de $scope
sont automatiquement détruits, c'est-à-dire dès que $ scope 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 différence majeure entre $ emit et $ broadcast est que les événements $ rootScope. $ Emit doivent être écoutés à l'aide de $ rootScope. $ On, car l'événement émis ne descend jamais dans l'arborescence des portées..
Dans ce cas aussi, vous devez détruire l'auditeur comme dans le cas de $ broadcast.
Edit:
Je préfère ne pas utiliser
$rootScope.$broadcast + $scope.$on
mais utiliser$rootScope.$emit+ $rootScope.$on
. Le combo$rootScope.$broadcast + $scope.$on
peut entraîner de graves problèmes de performances. C'est parce que l'événement va se propager à travers tous les domaines.
Edit 2:
Le problème traité dans cette réponse a été résolu dans la version 1.2.7 d'angular.js. $ broadcast évite maintenant les bulles sur les portées non enregistrées et s’exécute aussi rapidement que $ emit.
Vous devez utiliser $ rootScope pour envoyer et capturer des événements entre des contrôleurs de la même application. Injectez la dépendance $ rootScope à vos contrôleurs. 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 fonctionnent simplement dans le contrôleur de propriétaire. La communication entre les contrôleurs se fait via $ rootScope ou Services.
Vous pouvez appeler un service de votre contrôleur qui renvoie une promesse, puis l’utiliser dans votre contrôleur. Et utilisez ensuite $emit
ou $broadcast
pour informer les autres contrôleurs à ce sujet. Dans mon cas, je devais passer des appels http via mon service, alors j'ai fait quelque chose comme ceci:
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);
});
}
}])
<!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>
Ceci 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};
});
J'ai fini par ajouter une bibliothèque externe EventEmitter à projeter en tant que service et à l'injecter partout où j'avais besoin. Je peux donc "émettre" et "allumer" n'importe quoi n'importe où, sans me soucier de l'héritage. C'est moins de problèmes de cette façon et certainement une meilleure performance. Aussi plus lisible pour moi.
Prise en charge des caractères génériques: EventEmitter2
Bonne performance: eventemitter
Autre alternative: goutte à goutte
Les étendues peuvent être utilisées pour propager, envoyer un événement aux enfants ou au parent de la portée.
$ emit - propage l'événement au parent. $ broadcast - propage l'événement aux enfants. $ on - méthode d'écoute des é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/
Le code ci-dessous montre les deux sous-contrôleurs à partir desquels les événements sont envoyés vers le 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);
}
}
Selon l’événement angularjs docs, le destinataire devrait contenir des arguments avec une structure telle que
@param
- {objet} événement étant l'objet événement contenant des informations sur l'événement
- {Object} arguments qui sont passés par l'appelé (notez qu'il ne peut s'agir que d'un exemple, il est donc préférable d'envoyer toujours un objet dictionnaire).
$scope.$on('fooEvent', function (event, args) { console.log(args) });
À partir de votre code
De même, si vous essayez de mettre à disposition un élément d’information partagé entre différents contrôleurs, il existe un autre moyen d’y parvenir: les services angular. Depuis que les services sont des singletons, les informations peuvent être stockées controllers.Simply créer des fonctions getter et setter dans ce service, exposer ces fonctions, créer des variables globales dans le service et les utiliser pour stocker les informations
Le moyen le plus simple:
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>