Каков наилучший способ отменить распространение событий между вложенными вызовами ng-click?

Вот пример. Скажем, я хочу, чтобы изображение накладывалось подобно множеству сайтов. Поэтому, когда вы нажимаете миниатюру, над вашим окном появляется черная надпись, и в ней сосредоточена большая версия изображения. Щелчок на черном наложении отклоняет его; щелчок по изображению вызовет функцию, отображающую следующее изображение.

html:

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

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
    }
}

Проблема заключается в том, что при этой настройке, если вы щелкните изображение, вызываются как nextImage(), так и hideOverlay(). Но я хочу, чтобы вызывался только nextImage().

Я знаю, что вы можете захватывать и отменить событие в функции nextImage() следующим образом:

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

... Но я хочу знать, есть ли лучший способ AngularJS сделать это, что не потребует от меня префикса всех функций на элементах внутри наложения с помощью этого фрагмента.

Ответ 1

Что сказал @JosephSilber или передал объект $event в обратный вызов ng-click и остановил его распространение внутри него:

<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
}

Ответ 2

Используйте $event.stopPropagation():

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

Вот демо: http://plnkr.co/edit/3Pp3NFbGxy30srl8OBmQ?p=preview

Ответ 3

Мне нравится идея использовать для этого директиву:

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

Затем используйте директиву как:

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

Если бы вы хотели, вы могли бы сделать это решение более общим, как этот ответ, на другой вопрос: fooobar.com/questions/38474/...

Ответ 4

Иногда это может иметь смысл только для этого:

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

Я решил сделать это так, потому что я не хотел, чтобы myClickHandler() останавливал распространение события во многих других местах, которые он использовал.

Конечно, я мог бы добавить логический параметр к функции обработчика, но stopPropagation() гораздо более значим, чем просто true.

Ответ 5

Это работает для меня:

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

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

Ответ 6

Если вы не хотите добавлять распространение останова ко всем ссылкам, это также работает. Немного более масштабируемым.

$scope.hideOverlay( $event ){

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

}

Ответ 7

Если вы вставляете ng-click = "$ event.stopPropagation" в родительский элемент вашего шаблона, stopPropogation будет пойман, поскольку он пузырится по дереву, так что вам нужно только написать его один раз для всего вашего шаблона.

Ответ 8

Вы можете зарегистрировать другую директиву поверх ng-click, которая изменяет поведение по умолчанию ng-click и останавливает распространение события. Таким образом, вам не нужно будет добавлять $event.stopPropagation вручную.

app.directive('ngClick', function() {
    return {
        restrict: 'A',
        compile: function($element, attr) {
            return function(scope, element, attr) {
                element.on('click', function(event) {
                    event.stopPropagation();
                });
            };
        }
    }
});

Ответ 9

В контроллере IN используется

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