防止滑动触发ng-click处理程序

时间:2014-02-08 23:09:42

标签: javascript angularjs swipe angularjs-ng-click

我正在努力在HTML表格行上实现类似iOS的滑动到删除手势。例如,向左滑动Site11会将其从标准行转为:

A standard HTML table

进入可删除的行:

A standard HTML table with a delete-able HTML row

我有这个功能与ng-swipe-left指令一起使用。但是,我在每行上都有一个ng-click指令,导航到应用程序的不同视图。目前,当我在“Site11”文本本身上滑动结束时,在行上滑动时,之外触发这两个事件,而不是行中的任何其他位置。例如,此手势将触发ng-clickng-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指令中定义;只有当它的ID与控制器上的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的桌面版本中试过这个 - 我假设从鼠标注册中单击并拖动与移动设备上的滑动相同。

3 个答案:

答案 0 :(得分:14)

我也遇到了这种情况,我终于找到了一个棘手的方法来做到这一点 提到的$event.stopPropagation()只适用于ngClick。即使用$swipe event.stopPropagation()编写自定义滑动指令也无法阻止ngClick ...所以......

$swipe服务默认会触发“触摸”和“鼠标”事件。 ngSwipeLeft和ngSwipeRight指令也是如此 因此,当您进行滑动时,它将按以下顺序触发事件:

  1. touchStart
  2. touchMove
  3. touchEnd
  4. 鼠标按下
  5. mouseUp事件
  6. 点击
  7. 我通过鼠标拖动进行测试而不是直接触摸,但我的应用程序将在PC上的触摸屏上运行,并且此触摸屏上的滑动模仿鼠标拖动。因此,我的应用中$swipe服务'结束'事件的事件类型是'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
    }
    

    这对我有用。我希望这对你也有用。

答案 1 :(得分:0)

我现在也遇到同样的问题,实际上只在桌面浏览器上。我认为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

答案 2 :(得分:-3)

我终于能够设置我的开发环境,允许我在实际的移动设备上测试我的应用程序。我不再注意到这种行为 - 显然点击和拖动不一定与移动设备上的真实滑动相同。