web-dev-qa-db-fra.com

Comment arrêter les événements $ broadcast dans AngularJS?

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.

30
Noah Freitas

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/

43
kostik

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.

Jetez un coup d'œil à cette plunker ici: Plunkr

$scope.$on('test', function(event) { if (!event.defaultPrevented) { event.defaultPrevented = true; console.log('Handle event here for the root node only.'); } });

7
Mahendra Singh

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