web-dev-qa-db-fra.com

Quel est le meilleur moyen d'annuler la propagation d'événements entre des appels imbriqués avec un clic-clic?

Voici un exemple. Disons que je veux avoir une superposition d'image comme beaucoup de sites. Ainsi, lorsque vous cliquez sur une vignette, une incrustation noire apparaît sur toute la fenêtre et une version plus grande de l'image y est centrée. En cliquant sur la superposition noire, on la rejette. cliquer sur l'image appelle une fonction qui affiche l'image suivante.

Le html:

<div ng-controller="OverlayCtrl" class="overlay" ng-click="hideOverlay()">
    <img src="http://some_src" ng-click="nextImage()"/>
</div>

Le javascript:

function OverlayCtrl($scope) {
    $scope.hideOverlay = function() {
        // Some code to hdie the overlay
    }
    $scope.nextImage = function() {
        // Some code to find and display the next image
    }
}

Le problème est qu'avec cette configuration, si vous cliquez sur l'image, nextImage() et hideOverlay() sont tous deux appelés. Mais ce que je veux, c’est que seul nextImage() soit appelé.

Je sais que vous pouvez capturer et annuler l'événement dans la fonction nextImage() comme ceci:

if (window.event) {
    window.event.stopPropagation();
}

... Mais je veux savoir s’il existe une meilleure façon de procéder avec AngularJS qui ne me demandera pas de préfixer toutes les fonctions des éléments à l’intérieur de la superposition avec cet extrait.

178
cilphex

Ce que @JosephSilber a dit ou passer l'objet $ event dans ng-click callback et arrêter la propagation à l'intérieur de celui-ci:

<div ng-controller="OverlayCtrl" class="overlay" ng-click="hideOverlay()">
  <img src="http://some_src" ng-click="nextImage($event)"/>
</div>
$scope.nextImage = function($event) {
  $event.stopPropagation();
  // Some code to find and display the next image
}
184
Stewie

Utilisez $event.stopPropagation():

<div ng-controller="OverlayCtrl" class="overlay" ng-click="hideOverlay()">
    <img src="http://some_src" ng-click="nextImage(); $event.stopPropagation()" />
</div>

Voici une démo: http://plnkr.co/edit/3Pp3NFbGxy30srl8OBmQ?p=preview

169
Joseph Silber

J'aime l'idée d'utiliser une directive pour cela:

.directive('stopEvent', function () {
    return {
        restrict: 'A',
        link: function (scope, element, attr) {
            element.bind('click', function (e) {
                e.stopPropagation();
            });
        }
    };
 });

Puis utilisez la directive comme:

<div ng-controller="OverlayCtrl" class="overlay" ng-click="hideOverlay()">
    <img src="http://some_src" ng-click="nextImage()" stop-event/>
</div>

Si vous le souhaitez, vous pouvez rendre cette solution plus générique, comme celle-ci, à une question différente: https://stackoverflow.com/a/14547223/347216

100
David Ipsen

Parfois, il peut être plus logique de faire ceci:

<widget ng-click="myClickHandler(); $event.stopPropagation()"/>

J'ai choisi de le faire de cette façon car je ne voulais pas que myClickHandler() arrête la propagation de l'événement dans les nombreux autres endroits où il a été utilisé.

Bien sûr, j'aurais pu ajouter un paramètre booléen à la fonction de gestionnaire, mais stopPropagation() est beaucoup plus significatif que true.

29
Michael Scheper

Cela fonctionne pour moi:

<a href="" ng-click="doSomething($event)">Action</a>

this.doSomething = function($event) {
  $event.stopPropagation();
  $event.preventDefault();
};
7
Andrey Shatilov

Si vous ne souhaitez pas ajouter la propagation d'arrêt à tous les liens, cela fonctionne également. Un peu plus évolutif.

$scope.hideOverlay( $event ){

   // only hide the overlay if we click on the actual div
   if( $event.target.className.indexOf('overlay') ) 
      // hide overlay logic

}
4
Hampus Ahlgren

Si vous insérez ng-click = "$ event.stopPropagation" sur l'élément parent de votre modèle, stopPropogation sera intercepté lors de la projection dans l'arborescence. Vous ne devez donc l'écrire qu'une seule fois pour l'intégralité de votre modèle.

0
tbranch

Vous pouvez enregistrer une autre directive sur ng-click, qui modifie le comportement par défaut de ng-click et arrête la propagation de l'événement. De cette façon, vous n'auriez pas à ajouter $event.stopPropagation à la main.

app.directive('ngClick', function() {
    return {
        restrict: 'A',
        compile: function($element, attr) {
            return function(scope, element, attr) {
                element.on('click', function(event) {
                    event.stopPropagation();
                });
            };
        }
    }
});
0
bert
<div ng-click="methodName(event)"></div>

Utilisation du contrôleur IN

$scope.methodName = function(event) { 
    event.stopPropagation();
}
0
Dinesh Jain