Proper way to implement a swipeable tab with ng-swipe-left? (and ng-swipe-right)


#1

Hi, I’m trying to implement a swipeable tab panel but I ran into some trouble. It raises this message when I click and drag:

TypeError: e.gesture is undefined
if(Math.abs(e.gesture.deltaY) > 5) {
ionic.bundle.js (linha 6645)

Here’s my code:

Incudes in index.html

<script src="lib/js/ionic.bundle.js"></script>
<script src="lib/js/angular/angular-route.min.js"></script>
<script src="lib/js/angular/angular-touch.js"></script>
<script src="js/app.js"></script>

app.js is:

var nowon = angular.module(
'nowon',
[
'ionic',
'ngRoute',
'ngTouch',
'nowonControllers'
]);

The tab panel itself

<ion-tabs class="tabs-top">
  <ion-tab title="Promoções">
    <ion-content overflow-scroll="true" ng-swipe-left="alert('teste') ng-swipe-right="alert('teste')">
      <ion-list>
      ...content and properly closed tags

What am I doing wrong? Thanks in advance


#2

You shouldn’t be including Angular Router and touch, as ionic.bundle includes ui-router. Also Angular-Touch conflicts with our touch library.

http://ionicframework.com/docs/api/utility/ionic.EventController/#onGesture

We have exposing swipe gestures as a directive in our road map but right now you would make a directive to do this.


#3

I just made these, might help:

    angular.module('yourapp.directives')
.directive('onSwipeLeft', function($parse, $ionicGesture) {
    return {
        restrict :  'A',
        link : function(scope, elem, attrs) {
            var fn = $parse(attrs.onSwipeLeft);
            $ionicGesture.on('swipeleft', function(event) {
                //console.log("swiped left");
                scope.$apply(function() {
                    fn(scope, {$event:event});
                });
            }, elem);
        }
    }
});

angular.module('yourapp.directives')
.directive('onSwipeRight', function($parse, $ionicGesture) {
    return {
        restrict :  'A',
        link : function(scope, elem, attrs) {
            var fn = $parse(attrs.onSwipeRight);
            $ionicGesture.on('swiperight', function(event) {
                //console.log("swiped right");
                scope.$apply(function() {
                    fn(scope, {$event:event});
                });
            }, elem);
        }
    }
});

#4

Thank you, @mhartington! =)

@udi, I think I’m missing something here. I added your directives to my application but the function passed in the HTML is not being called. The directive is called, though: if I uncomment the console.log lines, they appear just fine in my JS console. Here’s my call:

<ion-content overflow-scroll="true" on-swipe-right="alert('lol')" on-swipe-left="alert('hue')">

None of the alerts are popping up but “swiped left/right” are logged just fine.


#5

I think the directive expects the function to exist on the scope, and this is why your alert isn’t working. Try referencing some function on the scope in your controller instead.

Truth is that I just took the ng-click code and modified it, so I’m not completely sure if the inner workings. But it works for me in this case, when I call my $scope.handleSwipe(dir) function.


#6

Thanks, it worked with a function in the $scope.


#7

I have a similar solution.
I was just wondering how you could achieve a result where there is also a side menu.
For example. If you look at the play store app on android you can swipe between tabs but you can also open the side menu with a swipe from the left edge of the screen.
I have played with it but haven’t found a real solution yet.
What I did/tried was detecting the swipe start and calculating the start position and direction of the swipe.


#8

@MGMsystems For the time being I disabled the side menu dragging and added a toggle button.


#9

I did the same.
But from a user point of view it would be nice to have both.


#10

@udi I just deployed my app to a phone (Nexus 5) and it takes forever to fire your swipe event. In a desktop browser it works just fine, though. Do you think there is anything to optimize it?


#11

The directive is pretty simple. You may want to ask the ionic folks about ionicGesture on that device, that’s the root cause of the event.


#12

I got it working.( For the menu to swipe open from the edge of the screen)
opened a pull request for it: https://github.com/driftyco/ionic/pull/1570


#13

Is it possibile to have a full example? I need a similar function. Thx


#14

@rockertux Please can you do a plunker or code pen of your solution? I have been trying to replicate the solution from the code @udi provided. Here is my HTML and JavaScript code below:

<!-- HTML -->

<ion-tabs class="tabs-striped tabs-top tabs-background-positive tabs-stable"><ion-tab title="House">
  <ion-content class="has-header has-tabs-top scroll-bg" overflow-scroll="true" ng-swipe-left="alert('teste')" ng-swipe-right="alert('teste')">
    <div class="row responive">
      <div class="col"><img src="http://placehold.it/160x120"></div>
      <div class="col"><img src="http://placehold.it/160x120"></div>
    </div>
    <div class="row responive">
      <div class="col"><img src="http://placehold.it/160x120"></div>
      <div class="col"><img src="http://placehold.it/160x120"></div>
    </div>
    <div class="row responive">
      <div class="col"><img src="http://placehold.it/160x120"></div>
      <div class="col"><img src="http://placehold.it/160x120"></div>
    </div>
    <div class="row responsive">
      <div class="col"><img src="http://placehold.it/160x120"></div>
      <div class="col"><img src="http://placehold.it/160x120"></div>
    </div>
  </ion-content>
</ion-tab><ion-tabs>


    <!-- JavaScript -->

   // Controller

   angular.module('starter', ['ionic', 'starter.services', 'starter.controllers'])
   .directive('onSwipeLeft', function($parse, $ionicGesture) {
    return {
        restrict :  'A',
        link : function(scope, elem, attrs) {
            var fn = $parse(attrs.onSwipeLeft);
            $ionic.onGesture('swipeleft', function(event) {
                //console.log("swiped left");
                scope.$apply(function() {
                    fn(scope, {$event:event});
                });
            }, elem);
        }
    }
})

.directive('onSwipeRight', function($parse, $ionicGesture) {
    return {
        restrict :  'A',
        link : function(scope, elem, attrs) {
            var fn = $parse(attrs.onSwipeRight);
            $ionic.onGesture('swiperight', function(event) {
                //console.log("swiped right");
                scope.$apply(function() {
                    fn(scope, {$event:event});
                });
            }, elem);
        }
    }
});

Thanks in advance!