Предотвратите прокрутку от запуска обработчика ng-click

Я работаю над реализацией жесткого жесткого диска типа iOS в строках таблицы HTML. Например, прокрутка влево на Site11 превратит его из стандартной строки:

A standard HTML table

в удаляемую строку:

A standard HTML table with a delete-able HTML row

У меня есть эта функциональность, работающая с директивой ng-swipe-left. Однако у меня также есть директива ng-click для каждой строки, которая переходит к другому представлению приложения. В настоящее время оба события запускаются, когда я выполняю салфетки в строке, за исключением случаев, когда салфетки заканчиваются на самом тексте "Site11", а не в другом месте внутри строки. Например, этот жест будет запускать как обработчики ng-click, так и ng-swipe-left:

enter image description here

но этот жест вызовет только обработчик ng-swipe-left:

enter image description here

Как я могу предотвратить выполнение обработчика ng-click, если в строке выполняется салфетка, независимо от того, где заканчивается салфетка?

Вот суть моей структуры HTML, которая определяет каждую строку:

<tr ng-repeat="item in items">
  <td ng-click="openDetailPane()"
      ng-swipe-left="$parent.swipeDeleteItemId = item.Id" 
      ng-swipe-right="$parent.swipeDeleteItemId = 'none'">
    <div list-item></div>
  </td>
  <td>
    <i class="fa fa-angle-right fa-2x" />
      <span>{{item.ChildCount}}</span>
  </td>
</tr>

Кнопка удаления определяется внутри директивы list-item; это видно только в том случае, если его идентификатор соответствует свойству swipeDeleteItemId на контроллере:

<div class="list-item">
  <span>{{item.Name}}</span>
  <div ng-class="{true: 'is-visible', false: ''}[item.Id === swipeDeleteItemId]">
    <div class="delete-item-swipe-button" 
         ng-mousedown="$event.stopPropagation();" 
         ng-click="$event.stopPropagation();">Delete</div>
  </div>
</div>

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

Ответ 1

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

Ответ 2

Я также встретил эту ситуацию, и я, наконец, нашел сложный способ сделать это.
$event.stopPropagation(), упомянутый где-то, работает только в ngClick. Даже писать пользовательскую директиву прокрутки $swipe с помощью event.stopPropagation() не может предотвратить ngClick... Итак...

Служба

$swipe по умолчанию запускает события "touch" и "mouse". Также действуют директивы ngSwipeLeft и ngSwipeRight.
Поэтому, когда вы делаете салфетки, он вызывает события в следующем порядке:

  • touchStart
  • TouchMove
  • touchEnd
  • MouseDown
  • MouseUp
  • выберите

Я тестировал мышью drag not touch напрямую, но мое приложение будет работать на сенсорном экране на ПК, а салфетки на этом сенсорном экране будут эмулировать перетаскивание мышью. Таким образом, тип события $swipe service "end" в моем приложении - "mouseup".
Затем вы можете использовать флаг, чтобы сделать что-то вроде этого:

<div ng-swipe-left="swipeFunc(); swiping=true;" ng-click="swiping ? ( swiping = false ) : clickFunc();">
   ...
</div>

или

<div ng-swipe-left="swipeFunc(); swiping=true;" ng-mouseup="clickFunc();" ng-click="swiping=false;">
  ...
</div>    

с clickFunc() следующим образом:

$scope.clickFunc = function() {
   if( $scope.swiping ) { return; }
   // do something
}

Это работает для меня. Надеюсь, это тоже полезно для вас.

Ответ 3

У меня такая же проблема и сейчас, и только на настольном браузере. Я думал, что preventDefault() или stopImmediatePropagation() сделает трюк, но нет. Тем не менее, я нашел решение для него. Попробуйте следующее:

angular.module('app', [])
.directive('noSwipeClick', function () {
    return function(scope, elm) {
        var el = angular.element(elm);
        el.bind('click', function(e) {
          if(scope.swipe.swiping === true) {
            e.stopPropagation();
            e.preventDefault();
          }
        });
    };
});

И в вашем HTML:

<div class="list-item">
  <span>{{item.Name}}</span>
  <div ng-class="{true: 'is-visible', false: ''}[item.Id === swipeDeleteItemId]">
    <div no-swipe-click class="delete-item-swipe-button" 
     ng-mousedown="$event.stopPropagation();" 
     ng-click="$event.stopPropagation();">Delete</div>
  </div>
</div>

Не забудьте назначить $scope.swipe.swiping = true в вашем контроллере при фактическом прокрутке и установить значение false при завершении