Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to swipe from left to right Ionic list item?

Tags:

I want to swipe Ionic list items to both sides. (i.e left-right AND right-left). It works perfectly for right-left swipe but I am not able to swipe list item to left side.

I used $ionicGesture for left-right swipe, and it also gives me an alert when i use swiperight event: event($ionicGesture.on('swiperight', scope.reportEvent, elem)), but I am not able to let it show the ion-option-button at the left side.

Here is my directive and controller code:

.directive('onSwipeRight', function($ionicGesture) {   return {     restrict :  'A',     link : function(scope, elem, attrs) {       var gestureType = attrs.gestureType;       switch(gestureType) {         case 'swipeRight':           $ionicGesture.on('swiperight', scope.reportEvent, elem);           break;         case 'swipeleft':           $ionicGesture.on('swipeleft', scope.reportEvent, elem);           break;         case 'doubletap':           $ionicGesture.on('doubletap', scope.reportEvent, elem);           break;         case 'tap':           $ionicGesture.on('tap', scope.reportEvent, elem);           break;       }      }   } })  .controller('ChatsCtrl', function($scope, Chats) {   // With the new view caching in Ionic, Controllers are only called   // when they are recreated or on app start, instead of every page change.   // To listen for when this page is active (for example, to refresh data),   // listen for the $ionicView.enter event:   //   //$scope.$on('$ionicView.enter', function(e) {   //});    $scope.chats = Chats.all();   $scope.remove = function(chat) {     Chats.remove(chat);   }    $scope.reportEvent = function (event) {     alert("hi");     console.log('Reporting : ' + event.type);     event.preventDefault(); };  }) 

Here is my html code.

<ion-view view-title="Chats">     <ion-content>         <ion-list can-swipe="true">             <ion-item gesture-type="swipeRight" on-swipe-right="swipeRight()" class="item-remove-animate item-avatar item-icon-right" ng-repeat="chat in chats" type="item-text-wrap" href="#/tab/chats/{{chat.id}}">                  <img ng-src="{{chat.face}}">                 <h2>{{chat.name}}</h2>                 <p>{{chat.lastText}}</p>                 <i class="icon ion-chevron-right icon-accessory"></i>                 <ion-option-button class="button-assertive" ng-click="share(item)" side="left">                     Share                 </ion-option-button>                 <ion-option-button class="button-assertive" ng-click="remove(chat)" side="right">                     Delete                 </ion-option-button>             </ion-item>         </ion-list>     </ion-content> </ion-view> 

So I want to display share button at left side and delete button at right side.

Can anybody provide me specific solution for it?

like image 715
arun kamboj Avatar asked Jul 01 '15 05:07

arun kamboj


People also ask

How do you use ion item sliding?

Swipe DirectionBy default, the buttons are placed on the "end" side. This means that options are revealed when the sliding item is swiped from end to start, i.e. from right to left in LTR, but from left to right in RTL.

How do you close ion item sliding?

The sliding item can be closed by grabbing a reference to ItemSliding . In the below example, the template reference variable slidingItem is placed on the element and passed to the share method.

How do you display lists in ionic?

List Header. Each list can include a header at the top of the list. We can include a list header by using the <ion-list-header> element.

How do you create an ionic list?

An ion-list can contain a header to display a title at the top of the list. The header is created by adding the component ion-list-header as the child of the ion-list. Items in the list can be separated using the component ion-item-divider.


1 Answers

I've edited ionic lib to do something like that. But i couldn't do a JSFiddle or a Code Pen i Will give you the link to my modified ionic.css and ionic.bundle.js!

TL;DR

https://gist.githubusercontent.com/booris/847f044d2ef2a05101ce/raw/2274365384f5eed3e4538b269f3a7d7998eb22ed/ionic.css

https://gist.githubusercontent.com/booris/847f044d2ef2a05101ce/raw/2274365384f5eed3e4538b269f3a7d7998eb22ed/ionic.bundle.js

Just replace it with yours, start an ionic project blank. And put this HTML in it:

 <body ng-app="starter">        <ion-pane>             <ion-header-bar class="bar-stable">                 <h1 class="title">Ionic Blank Starter</h1>             </ion-header-bar>             <ion-content>                 <ion-list show-delete="false" can-swipe="true" swipe-direction="both">                     <ion-item href="#">                         Item 1                         <ion-option-button side="right" class="button-light icon ion-heart"></ion-option-button>                         <ion-option-button side="right" class="button-light icon ion-email"></ion-option-button>                         <ion-option-button side="left" class="button-assertive icon ion-trash-a"></ion-option-button>                     </ion-item>                     <ion-item href="#">                         Item 2                         <ion-option-button class="button-light icon ion-heart"></ion-option-button>                         <ion-option-button class="button-light icon ion-email"></ion-option-button>                         <ion-option-button class="button-assertive icon ion-trash-a"></ion-option-button>                     </ion-item>                 </ion-list>             </ion-content>         </ion-pane>   </body> 

You can specify the wipe direction with left, right or both. And in the ion-options-button you can give it a side.

Hope it helps, anything you need just ask! I will try to comment my changes in the code later on!

EDIT: I will try to explain what i did.

First change the ionOptionButton directive to create to div for the button, one left and one right

 //added second div with class item-options-left for the left buttons  var ITEM_TPL_OPTION_BUTTONS =         '<div class="item-options invisible">' +         '</div>' + '<div class="item-options-left invisible">' +          '</div>'; IonicModule.directive('ionOptionButton', [function () {     function stopPropagation(e) {         e.stopPropagation();     }     return {         restrict: 'E',         require: '^ionItem',         priority: Number.MAX_VALUE,         compile: function ($element, $attr) {             $attr.$set('class', ($attr['class'] || '') + ' button', true);             return function ($scope, $element, $attr, itemCtrl) {                  if (!itemCtrl.optionsContainer) {                     itemCtrl.optionsContainer = jqLite(ITEM_TPL_OPTION_BUTTONS);                     itemCtrl.$element.append(itemCtrl.optionsContainer);                 }                  //[NEW] if it as an attribute side = 'left' put the button in the left container                 if ($attr.side === 'left') {                     angular.element(itemCtrl.optionsContainer[1]).append($element);                     itemCtrl.$element.addClass('item-left-editable');                 } else{                     angular.element(itemCtrl.optionsContainer[0]).append($element);                     itemCtrl.$element.addClass('item-right-editable');                 }                  //Don't bubble click up to main .item                 $element.on('click', stopPropagation);             };         }     }; }]); 

Add CSS to left buttons in ionic.css file

.item-options-left {   position: absolute;   top: 0;   left: 0;   z-index: 1;   height: 100%; } .item-options-left .button {   height: 100%;   border: none;   border-radius: 0;   display: -webkit-inline-box;   display: -webkit-inline-flex;   display: -moz-inline-flex;   display: -ms-inline-flexbox;   display: inline-flex;   -webkit-box-align: center;   -ms-flex-align: center;   -webkit-align-items: center;   -moz-align-items: center;   align-items: center; } .item-options .button:before {   margin: 0 auto; } 

Now change the ion-list controller to accept swipe directions attribute

.controller('$ionicList', [   '$scope',   '$attrs',   '$ionicListDelegate',   '$ionicHistory', function ($scope, $attrs, $ionicListDelegate, $ionicHistory) {             var self = this;              //[NEW] object with can-swipe attr and swipe-direction side attr, default direction is left             var swipe = {                 isSwipeable: true,                 side: 'left'             };             var isReorderShown = false;             var isDeleteShown = false;              var deregisterInstance = $ionicListDelegate._registerInstance(                 self, $attrs.delegateHandle,                 function () {                     return $ionicHistory.isActiveScope($scope);                 }             );             $scope.$on('$destroy', deregisterInstance);              self.showReorder = function (show) {                 if (arguments.length) {                     isReorderShown = !!show;                 }                 return isReorderShown;             };              self.showDelete = function (show) {                 if (arguments.length) {                     isDeleteShown = !!show;                 }                 return isDeleteShown;             };              //[NEW] get swipe direction attribute and store it in a variable to access in other function             self.canSwipeItems = function (can) {                 if (arguments.length) {                     swipe.isSwipeable = !!can;                     swipe.side = $attrs.swipeDirection;                 }                 return swipe;             };              self.closeOptionButtons = function () {                 self.listView && self.listView.clearDragEffects();             }; }]); 

To end, you should replace slideDrag function with this one, just search for it in ionic.bundle.js

//[NEW] add this var to the others in the function var ITEM_OPTIONS_CLASS_RIGHT = 'item-options-left';  var SlideDrag = function (opts) {         this.dragThresholdX = opts.dragThresholdX || 10;         this.el = opts.el;         this.item = opts.item;         this.canSwipe = opts.canSwipe;     };      SlideDrag.prototype = new DragOp();      SlideDrag.prototype.start = function (e) {         var content, buttonsLeft, buttonsRight, offsetX, buttonsLeftWidth, buttonsRightWidth;          if (!this.canSwipe().isSwipeable) {             return;         }          if (e.target.classList.contains(ITEM_CONTENT_CLASS)) {             content = e.target;         } else if (e.target.classList.contains(ITEM_CLASS)) {             content = e.target.querySelector('.' + ITEM_CONTENT_CLASS);         } else {             content = ionic.DomUtil.getParentWithClass(e.target, ITEM_CONTENT_CLASS);         }          // If we don't have a content area as one of our children (or ourselves), skip         if (!content) {             return;         }          // Make sure we aren't animating as we slide         content.classList.remove(ITEM_SLIDING_CLASS);          // Grab the starting X point for the item (for example, so we can tell whether it is open or closed to start)         offsetX = parseFloat(content.style[ionic.CSS.TRANSFORM].replace('translate3d(', '').split(',')[0]) || 0;          // Grab the buttons         buttonsLeft = content.parentNode.querySelector('.' + ITEM_OPTIONS_CLASS);         if (!buttonsLeft) {             return;         }          //[NEW] get the Right buttons         buttonsRight = content.parentNode.querySelector('.' + ITEM_OPTIONS_CLASS_RIGHT);         if (!buttonsRight) {             return;         }          // [NEW] added the same functionality to both sides, to make buttons visible when dragged         if(e.gesture.direction === "left")             buttonsLeft.classList.remove('invisible');         else             buttonsRight.classList.remove('invisible');          //[NEW] added buttonRight and buttonLeft properties to currentDrag          buttonsLeftWidth = buttonsLeft.offsetWidth;         buttonsRightWidth = buttonsRight.offsetWidth;          this._currentDrag = {             buttonsLeft: buttonsLeft,             buttonsRight: buttonsRight,             buttonsLeftWidth: buttonsLeftWidth,             buttonsRightWidth: buttonsRightWidth,             content: content,             startOffsetX: offsetX         };     };      /**      * Check if this is the same item that was previously dragged.      */     SlideDrag.prototype.isSameItem = function (op) {         if (op._lastDrag && this._currentDrag) {             return this._currentDrag.content == op._lastDrag.content;         }         return false;     };      SlideDrag.prototype.clean = function (isInstant) {         var lastDrag = this._lastDrag;          if (!lastDrag || !lastDrag.content) return;          lastDrag.content.style[ionic.CSS.TRANSITION] = '';         lastDrag.content.style[ionic.CSS.TRANSFORM] = '';         if (isInstant) {             lastDrag.content.style[ionic.CSS.TRANSITION] = 'none';             makeInvisible();             ionic.requestAnimationFrame(function () {                 lastDrag.content.style[ionic.CSS.TRANSITION] = '';             });         } else {             ionic.requestAnimationFrame(function () {                 setTimeout(makeInvisible, 250);             });         }          function makeInvisible() {             lastDrag.buttonsLeft && lastDrag.buttonsLeft.classList.add('invisible');             lastDrag.buttonsRight && lastDrag.buttonsRight.classList.add('invisible');         }     };      SlideDrag.prototype.drag = ionic.animationFrameThrottle(function (e) {         var buttonsLeftWidth;         var buttonsRightWidth;          // We really aren't dragging         if (!this._currentDrag) {             return;         }          // Check if we should start dragging. Check if we've dragged past the threshold,         // or we are starting from the open state.         if (!this._isDragging &&             ((Math.abs(e.gesture.deltaX) > this.dragThresholdX) ||                 (Math.abs(this._currentDrag.startOffsetX) > 0))) {             this._isDragging = true;         }          if (this._isDragging) {             buttonsLeftWidth = this._currentDrag.buttonsLeftWidth;             buttonsRightWidth = this._currentDrag.buttonsRightWidth;              // Grab the new X point, capping it at zero             //[NEW] added right swipe new position             if (this.canSwipe().side === 'left' || (this.canSwipe().side === 'both' && e.gesture.direction === 'left'))                 var newX = Math.min(0, this._currentDrag.startOffsetX + e.gesture.deltaX);             else if (this.canSwipe().side === 'right' || (this.canSwipe().side === 'both' && e.gesture.direction === 'right'))                 var newX = Math.max(0, this._currentDrag.startOffsetX + e.gesture.deltaX);              var buttonsWidth = 0;             if (e.gesture.direction === 'right')                 buttonsWidth = buttonsRightWidth;             else                 buttonsWidth = buttonsLeftWidth;             // If the new X position is past the buttons, we need to slow down the drag (rubber band style)              if (newX < -buttonsWidth) {                 // Calculate the new X position, capped at the top of the buttons                 newX = Math.min(-buttonsWidth, -buttonsWidth + (((e.gesture.deltaX + buttonsWidth) * 0.4)));             }                this._currentDrag.content.$$ionicOptionsOpen = newX !== 0;              this._currentDrag.content.style[ionic.CSS.TRANSFORM] = 'translate3d(' + newX + 'px, 0, 0)';             this._currentDrag.content.style[ionic.CSS.TRANSITION] = 'none';         }     });      SlideDrag.prototype.end = function (e, doneCallback) {         var self = this;          // There is no drag, just end immediately         if (!self._currentDrag) {             doneCallback && doneCallback();             return;         }          // If we are currently dragging, we want to snap back into place         // The final resting point X will be the width of the exposed buttons         var restingPoint;         if (e.gesture.direction === 'left' && (this.canSwipe().side === 'left' || this.canSwipe().side === 'both'))             restingPoint = -self._currentDrag.buttonsLeftWidth;         if (e.gesture.direction === 'right' && (this.canSwipe().side === 'right' || this.canSwipe().side === 'both'))             restingPoint = self._currentDrag.buttonsRightWidth;          // Check if the drag didn't clear the buttons mid-point         // and we aren't moving fast enough to swipe open         var buttonsWidth = 0;         if (e.gesture.direction === 'right')              buttonsWidth = self._currentDrag.buttonsRightWidth;         else              buttonsWidth = self._currentDrag.buttonsLeftWidth;         if (e.gesture.deltaX > -(buttonsWidth / 2)) {              // If we are going left or right but too slow, or going right, go back to resting             if ((e.gesture.direction == "left" || e.gesture.direction == "right")  && Math.abs(e.gesture.velocityX) < 0.3) {                 restingPoint = 0;             }           }          ionic.requestAnimationFrame(function () {             if (restingPoint === 0) {                 self._currentDrag.content.style[ionic.CSS.TRANSFORM] = '';                 var buttonsLeft = self._currentDrag.buttonsLeft;                 var buttonsRight = self._currentDrag.buttonsRight;                 setTimeout(function () {                     buttonsLeft && buttonsLeft.classList.add('invisible');                     buttonsRight && buttonsRight.classList.add('invisible');                 }, 250);             } else {                 self._currentDrag.content.style[ionic.CSS.TRANSFORM] = 'translate3d(' + restingPoint + 'px,0,0)';             }             self._currentDrag.content.style[ionic.CSS.TRANSITION] = '';               // Kill the current drag             if (!self._lastDrag) {                 self._lastDrag = {};             }             ionic.extend(self._lastDrag, self._currentDrag);             if (self._currentDrag) {                 self._currentDrag.buttons = null;                 self._currentDrag.content = null;             }             self._currentDrag = null;              // We are done, notify caller             doneCallback && doneCallback();         });     }; 

My solution is not perfect, but it works. and there are others ways of doing this, i did it this way to understand better how Ionic works and how they do Ionic directives.

Any feedback is welcome, and with this you can try to make your own or improve this one.

like image 162
cagica Avatar answered Sep 20 '22 07:09

cagica