J'ai un footerController et un codeScannerController avec différentes vues.
angular.module('myApp').controller('footerController', ["$scope", function($scope) {}]);
angular.module('myApp').controller('codeScannerController', ["$scope", function($scope) {
console.log("start");
$scope.startScanner = function(){...
Lorsque je clique sur un <li>
dans footer.html, je devrais obtenir cet événement dans codeScannerController.
<li class="button" ng-click="startScanner()">3</li>
Je pense que cela peut être réalisé avec $on
et $broadcast
, mais je ne sais pas comment et je ne peux pas trouver d’exemples nulle part.
Si vous voulez $broadcast
utilisez le $rootScope
:
$scope.startScanner = function() {
$rootScope.$broadcast('scanner-started');
}
Et puis pour recevoir, utilisez le $scope
de votre contrôleur:
$scope.$on('scanner-started', function(event, args) {
// do what you want to do
});
Si vous le souhaitez, vous pouvez passer des arguments lorsque vous $broadcast
:
$rootScope.$broadcast('scanner-started', { any: {} });
Et ensuite les recevoir:
$scope.$on('scanner-started', function(event, args) {
var anyThing = args.any;
// do what you want to do
});
Documentation à ce sujet à l'intérieur de Scope docs .
Tout d’abord, une brève description de $on()
, $broadcast()
ET $emit()
:
.$on(name, listener)
- Écoute un événement spécifique par un name
donné.$broadcast(name, args)
- Diffuse un événement via le $scope
de tous les enfants.$emit(name, args)
- Émet un événement vers le haut de la hiérarchie $scope
à tous les parents, y compris le $rootScope
Basé sur le code HTML suivant (voir exemple complet ici ):
<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>
Les événements déclenchés traverseront le $scopes
comme suit:
$scope
$scope
puis $rootScope
$scope
puis par le contrôleur 3 $scope
$scope
puis $rootScope
$scope
$scope
, le contrôleur 2 $scope
puis $rootScope
$rootScope
et $scope
de tous les contrôleurs (1, 2 puis 3).$rootScope
JavaScript pour déclencher des événements (encore une fois, vous pouvez voir un exemple de travail ici ):
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');
});
}]);
Une chose que vous devez savoir, c'est que $ prefix fait référence à une méthode Angular, les préfixes $$ se rapportant à angular méthodes que vous devriez éviter d'utiliser.
vous trouverez ci-dessous un exemple de modèle et ses contrôleurs. Nous verrons comment $ broadcast/$ on peut nous aider à atteindre nos objectifs.
<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>
Les contrôleurs sont
app.controller('FirstCtrl', function($scope){
$scope.register = function(){
}
});
app.controller('SecondCtrl', function($scope){
});
Ma question est la suivante: comment passez-vous le nom du second contrôleur lorsqu'un utilisateur clique sur le registre? Vous pouvez proposer plusieurs solutions, mais celle que nous allons utiliser utilise $ broadcast et $ on.
$ broadcast vs $ emit
Que devrions-nous utiliser? $ broadcast transmettra tous les éléments dom enfants et $ emit canalisera la direction opposée à tous les éléments ancom dom.
Le meilleur moyen d'éviter de décider entre $ emit ou $ broadcast est de canaliser à partir de $ rootScope et d'utiliser $ broadcast pour tous ses enfants. Ce qui rend notre cas beaucoup plus facile puisque nos éléments de dom sont des frères et soeurs.
Ajout de $ rootScope et permet à $ broadcast
app.controller('FirstCtrl', function($rootScope, $scope){
$scope.register = function(){
$rootScope.$broadcast('BOOM!', $scope.name)
}
});
Notez que nous avons ajouté $ rootScope et que nous utilisons maintenant $ broadcast (broadcastName, arguments). Pour broadcastName, nous voulons lui attribuer un nom unique afin que nous puissions saisir ce nom dans notre secondCtrl. J'ai choisi BOOM! juste pour le fun. Le second argument, "arguments", nous permet de transmettre des valeurs aux auditeurs.
Recevoir notre émission
Dans notre deuxième contrôleur, nous devons configurer le code pour écouter notre diffusion
app.controller('SecondCtrl', function($scope){
$scope.$on('BOOM!', function(events, args){
console.log(args);
$scope.name = args; //now we've registered!
})
});
C'est vraiment aussi simple que cela. Exemple en direct
Autres moyens d'obtenir des résultats similaires
Essayez d'éviter d'utiliser cette suite de méthodes, car elle n'est ni efficace, ni facile à gérer, mais constitue un moyen simple de résoudre les problèmes que vous pourriez rencontrer.
Vous pouvez généralement faire la même chose en utilisant un service ou en simplifiant vos contrôleurs. Nous ne discuterons pas de cela en détail mais je pensais que je le mentionnerais simplement pour être complet.
Enfin, gardez à l'esprit une émission très utile à écouter: "$ destroy": vous pouvez voir que $ signifie qu'il s'agit d'une méthode ou d'un objet créé par les codes de fournisseur. Quoi qu'il en soit, $ destroy est diffusé quand un contrôleur est détruit, vous pouvez l'écouter pour savoir quand votre contrôleur est supprimé.
//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();
};
}); }());