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.
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
}
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
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
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
.
Cela fonctionne pour moi:
<a href="" ng-click="doSomething($event)">Action</a>
this.doSomething = function($event) {
$event.stopPropagation();
$event.preventDefault();
};
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
}
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.
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();
});
};
}
}
});
<div ng-click="methodName(event)"></div>
Utilisation du contrôleur IN
$scope.methodName = function(event) {
event.stopPropagation();
}