AngularJS click-stopPropagation

356

У меня есть событие "Событие" в строке таблицы, и в этой строке есть кнопка "Удалить" с кликом "Событие" . Когда я нажимаю кнопку "Удалить", также запускается событие "Событие" в строке.

Вот мой код.

<tbody>
  <tr ng-repeat="user in users" class="repeat-animation" ng-click="showUser(user, $index)">
    <td>{{user.firstname}}</td>
    <td>{{user.lastname}}</td>
    <td>{{user.email}}</td>
    <td><button class="btn red btn-sm" ng-click="deleteUser(user.id, $index)">Delete</button></td>
  </tr>
</tbody>

Как я могу предотвратить запуск события showUser при нажатии кнопки удаления в ячейке таблицы?

Теги:
angularjs-ng-click

5 ответов

709
Лучший ответ
Директива

ngClick (как и все другие директивы событий) создает переменную $event, доступную в той же области. Эта переменная является ссылкой на объект JS event и может использоваться для вызова stopPropagation():

<table>
  <tr ng-repeat="user in users" ng-click="showUser(user)">
    <td>{{user.firstname}}</td>
    <td>{{user.lastname}}</td>
    <td>
      <button class="btn" ng-click="deleteUser(user.id, $index); $event.stopPropagation();">
        Delete
      </button>
    </td>              
  </tr>
</table>

PLUNKER

  • 2
    Я не мог понять, доступно ли это в коде контроллера - $ scope. $ Event, похоже, не работает. Есть идеи?
  • 91
    Объект @event создается внутри директивы ng-click, и вы можете передать его в функцию ng-click обработчик ng-click="deleteUser(user.id, $event)" : ng-click="deleteUser(user.id, $event)" .
Показать ещё 7 комментариев
103

В дополнение к ответу Стьюи. Если ваш обратный вызов решает, следует ли остановить распространение или нет, мне было полезно передать объект $event в обратный вызов:

<div ng-click="parentHandler($event)">
  <div ng-click="childHandler($event)">
  </div>
</div>

И затем в самом обратном вызове вы можете решить, следует ли останавливать распространение события:

$scope.childHandler = function ($event) {
  if (wanna_stop_it()) {
    $event.stopPropagation();
  }
  ...
};
  • 9
    это более элегантно, чем выполнять несколько выражений в атрибуте html, спасибо
  • 3
    Не забудьте указать аргумент $ event в директиве html ng-click. Сначала я наткнулся на это.
Показать ещё 2 комментария
10

Я написал директиву, которая позволяет вам ограничить области, где действует клик. Он может использоваться для определенных сценариев, подобных этому, поэтому вместо того, чтобы иметь дело с щелчком по каждому случаю, вы можете просто сказать, что "клики не выйдут из этого элемента".

Вы бы использовали его следующим образом:

<table>
  <tr ng-repeat="user in users" ng-click="showUser(user)">
    <td>{{user.firstname}}</td>
    <td>{{user.lastname}}</td>
    <td isolate-click>
      <button class="btn" ng-click="deleteUser(user.id, $index);">
        Delete
      </button>
    </td>              
  </tr>
</table>

Имейте в виду, что это предотвратит все клики по последней ячейке, а не только кнопку. Если это не то, что вы хотите, вы можете обернуть эту кнопку следующим образом:

<span isolate-click>
    <button class="btn" ng-click="deleteUser(user.id, $index);">
        Delete
    </button>
</span>

Вот код директивы:

angular.module('awesome', []).directive('isolateClick', function() {
    return {
        link: function(scope, elem) {
            elem.on('click', function(e){
                e.stopPropagation();
            });
        }
   };
});
  • 0
    Ницца! Я переименовал вашу директиву в ngClick , так как фактически никогда не хочу распространять уже обработанное событие.
  • 1
    Будьте осторожны с этим. Некоторые другие плагины могут действительно хотеть слушать эти щелчки. Если вы используете всплывающие подсказки при щелчке снаружи, они могут никогда не закрыться, поскольку внешние щелчки не распространяются на тело.
Показать ещё 2 комментария
0

В случае, если вы используете такую ​​директиву, как я, так это то, как это работает, когда вам требуется привязка к двум каналам данных, например, после обновления атрибута в любой модели или коллекции:

angular.module('yourApp').directive('setSurveyInEditionMode', setSurveyInEditionMode)

function setSurveyInEditionMode() {
  return {
    restrict: 'A',
    link: function(scope, element, $attributes) {
      element.on('click', function(event){
        event.stopPropagation();
        // In order to work with stopPropagation and two data way binding
        // if you don't use scope.$apply in my case the model is not updated in the view when I click on the element that has my directive
        scope.$apply(function () {
          scope.mySurvey.inEditionMode = true;
          console.log('inside the directive')
        });
      });
    }
  }
}

Теперь вы можете легко использовать его в любой кнопке, ссылке, div и т.д. так:

<button set-survey-in-edition-mode >Edit survey</button>
-13
<ul class="col col-double clearfix">
 <li class="col__item" ng-repeat="location in searchLocations">
   <label>
    <input type="checkbox" ng-click="onLocationSelectionClicked($event)" checklist-model="selectedAuctions.locations" checklist-value="location.code" checklist-change="auctionSelectionChanged()" id="{{location.code}}"> {{location.displayName}}
   </label>



$scope.onLocationSelectionClicked = function($event) {
      if($scope.limitSelectionCountTo &&         $scope.selectedAuctions.locations.length == $scope.limitSelectionCountTo) {
         $event.currentTarget.checked=false;
      }
   };

  • 6
    Не могли бы вы объяснить, почему вы думаете, что это отвечает на вопрос?
  • 0
    Это как бы отвечает на вопрос. Он показывает, как передать событие в обратный вызов, что больше, чем предполагалось в первоначальном вопросе.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню