问题
In my angular application, the body has a ng-swipe
right and left to toggle a sidebar. The problem is when in my page I have a scrollable horizontal DIV. It won't scroll because of the swipe of the body.
<body ng-swipe-right="sidebar = true" ng-swipe-left="sidebar = false">
<div class="scrollable-x">long content that overflow on x</div>
</body>
Is there a way to prevent from swiping and to let the scroll of the child element?
I tried to set $event.stopPropagation()
on the swipe of the div so the scrollbar is not toggled anymore but the content won't scroll.
Any idea?
回答1:
UPDATE
Looked at allenhwkim's answer and indeed he is correct, that $event
's propagation can be easily stopped. I took it for granted (without checking), that attaching ng-swipe-*
directive to other element will start firing separate events. I was clearly wrong.
HERE is updated fiddle.
The below answer is basically rubbish.
There is still one problem with stopPropagation
-- the mouse up event seems not to fire.
The most elegant solution would be to decorate the ng-swipe-*
directives or $swipe
service -- but looking into their code and I do not think it is possible.
Other option would be to create your own directive, that would manually attach ng-swipe-*
, take care of the compilation process and provide desired functionality. Surely, bit complicated.
What I came up with is a quick hack. The idea is to add an attribute to an element whose descendants should not fire the ng-swipe-*
.
js
myApp.value('shouldFire', function(element){
var update = true;
// strange enough $event.fromElement is always null
var current = element;
while(current && current != document.body){
if(current.getAttribute('swipe')=='cancel'){
update = false;
break;
}
current = current.parentElement;
}
return update;
})
function MyCtrl($scope, shouldFire) {
$scope.sidebar = false;
$scope.updateSidebar = function($event, show){
var element = $event.toElement || $event.srcElement;
shouldFire(element) && ($scope.sidebar = show);
}
}
html
<div class="cont" ng-swipe-right="updateSidebar($event, true)"
ng-swipe-left="updateSidebar($event, false)">
...
<div class="pan-container" panhandler=""
content-width="500px" swipe="cancel">
UPDATED DEMO
caution
- in android's chrome.v.39 angular-panhandler is broken.
$event
stores a proper touch event (android's chrome) or a custom event (desktop's chrome); in the latter case$event.fromElement
is alwaysnull
.- The proposed solution is a quick hack -- it is neither elegant nor general. Nonetheless, theoretically it could be possible to support multi
ng-swipe-*
handlers by setting different values inswipe
attribute.
回答2:
$event.stopProgagation()
must work. I don't know why yours not work.
http://plnkr.co/edit/AqczfhAVGMXNOcJij0JE?p=preview
var app = angular.module('myApp',['ngTouch']);
app.controller("MyCtrl", function($scope) {
$scope.void = function(evt){
evt.stopPropagation();
}
});
The common sense to me is that swiping and scroll left/right are different.
swiping is about moving fast. If you do not move fast. it's not swiping. When you scroll slowly, swiping does not happen.
I think all users know about this(maybe not). If not, I would recommend UX approach to let the user scroll slowly by showing some button or whatever, and leaving swipe as it is.
Anyhow, there is a way to disabling swipe using stopPropagation
Let me know if this plnkr does not satisfy your requirement.
回答3:
It's like this. In your scrollable element (usually it's the dom element you set as overflow-x: scroll), add ng-swipe-right="preventScrollingFunction($event)", like so:
<div ng-swipe-right="preventScrollingFunction($event)">...</div>
Then, in the scope create the function:
$scope.preventScrollingFunction = function($event) {
$event.stopPropagation();
}
That should do it!
Note: make sure the parameter for the function is exactly $event, as it is inyected by Angular and if you name it $evt or $e or whatever, it wont work.
来源:https://stackoverflow.com/questions/25241168/cancel-ng-swipe-right-on-child