Existe-t-il un moyen intégré permettant d'empêcher les événements $broadcast
de descendre dans la chaîne d'étendue?
L'objet événement transmis par un événement $broadcast
n'a pas de méthode stopPropagation
(comme le docs sur $ rootScope mention.) Cependant, cette demande d'extraction fusionnée suggère que les événements $broadcast
peuvent être appelés stopPropagation
.
Extraits de code source d'angularJS 1.1.2:
$emit: function(name, args) {
// ....
event = {
name: name,
targetScope: scope,
stopPropagation: function() {
stopPropagation = true;
},
preventDefault: function() {
event.defaultPrevented = true;
},
defaultPrevented: false
},
// ....
}
$broadcast: function(name, args) {
// ...
event = {
name: name,
targetScope: target,
preventDefault: function() {
event.defaultPrevented = true;
},
defaultPrevented: false
},
// ...
}
Comme vous pouvez le voir, l'objet event dans $ broadcast n'a pas "stopPropagation".
Au lieu de stopPropagation, vous pouvez utiliser preventDefault afin de marquer l’événement comme "pas nécessaire de gérer cet événement". Cela ne stoppe pas la propagation de l’événement, mais indiquera aux portées des enfants: "pas besoin de gérer cet événement"
Exemple: http://jsfiddle.net/C8EqT/1/
Puisque broadcast n'a pas la méthode stopPropagation, vous devez utiliser la propriété defaultPrevented, ce qui est logique dans les directives récursives.
$scope.$on('test', function(event) {
if (!event.defaultPrevented) {
event.defaultPrevented = true;
console.log('Handle event here for the root node only.');
}
});
J'ai mis en place un voleur d'événements à cette fin:
.factory("stealEvent", [function () {
/**
* If event is already "default prevented", noop.
* If event isn't "default prevented", executes callback.
* If callback returns a truthy value or undefined,
* stops event propagation if possible, and flags event as "default prevented".
*/
return function (callback) {
return function (event) {
if (!event.defaultPrevented) {
var stopEvent = callback.apply(null, arguments);
if (typeof stopEvent === "undefined" || stopEvent) {
event.stopPropagation && event.stopPropagation();
event.preventDefault();
}
}
};
};
}]);
Utiliser:
$scope.$on("AnyEvent", stealEvent(function (event, anyOtherParameter) {
if ($scope.keepEvent) {
// do some stuff with anyOtherParameter
return true; // steal event
} else {
return false; // let event available for other listeners
}
}));
$scope.$on("AnyOtherEvent", stealEvent(function (event, anyOtherParameter) {
// do some stuff with anyOtherParameter, event stolen by default
}));