Click to slide open ion-item-sliding instead of swiping

#1

Hello,

I would like to know if it is possible to trigger the slide animation on a ion-item-sliding element when clicked on a button for example.

Right now you have to swipe for the animation to trigger and reveal the buttons underneath, but is it possible to trigger that with a click event?

1 Like
Click to slide open and close ion-item-sliding on Ionic 4
#2

Greate question, I’m trying to reproduce the sliding animation on a click too :slight_smile: . Unfortunatly I did not figured out how to do it. Did you find a way ?

1 Like
#3

No, I wanted it to be an extra feature on a project, but decided to move on as I did not find a solution.

1 Like
#4

Ok, I finally found a solution, I tried to reproduce what I saw in the inspector.
then this code works for me

public open(itemSlide: ItemSliding, item: Item) {

        // reproduce the slide on the click
        itemSlide.setCssClass("active-sliding", true);
        itemSlide.setCssClass("active-slide", true);
        itemSlide.setCssClass("active-options-right", true);
        item.setCssStyle("transform", "translate3d(-144px, 0px, 0px)")

    }

and when I’m clicking on the item to close it back

 public close(item: ItemSliding) {
        item.close();
        item.setCssClass("active-slide", false);
        item.setCssClass("active-slide", false);
        item.setCssClass("active-options-right", false);
    }
5 Likes
#5

Thanks for posting I have been trying to find a solution to the same issue as well, I tried out your sample of code however on the click event for toggling the item-slide I got this error: “ORIGINAL EXCEPTION: TypeError: Cannot read property ‘setCssClass’ of undefined”. Would you happen to know a solution to this and if possible would you also share the html used to produce your results? Thank you! :slight_smile:

#6

seems that you did not pass the right parameter in your HTML. Check this if it can help

<ion-list>
        <ion-item-sliding #slidingItem *ngFor="let conversation of conversations">
            <ion-item #item (click)="open(slidingItem, item)">
                <ion-avatar item-left (click)="open(slidingItem)">
                    <img src="build/assets/images/coins.png">
                </ion-avatar>
                <h3>{{conversation.user.username}}</h3>
                <p [ngClass]="{'unviewed': conversation.state == 'unviewed'}">{{conversation.excerpt}}</p>
                <p item-right>{{conversation.lastUpdate.toLocaleDateString()}}</p>
            </ion-item>
            <ion-item-options side="right" (click)="close(slidingItem)">
                <button (click)="goRoom(conversation)"><ion-icon name="chatbubbles"></ion-icon></button>
                <button><ion-icon name="person"></ion-icon></button>
            </ion-item-options>
        </ion-item-sliding>
    </ion-list>
2 Likes
#7

This has been so much help, the problem was as you mentioned that I didn’t have the correct parameters in my html. It does work now! Thanks again for the help I am sure that this will be useful to others as well! :smiley:

#8

First of all, thanks for the code @Mxman06. Your answer helped me a lot.

But, with the changes on Ionic2 rc.0, I had to change my code to work on the new background code. For this, I just changed the “setCssClass” to the new method “setElementClass”, and “setCssStyle” to “setElementStyle”. The solution is in the code below.

public open(itemSlide: ItemSliding, item: Item) {
    // reproduce the slide on the click
    itemSlide.setElementClass("active-sliding", true);
    itemSlide.setElementClass("active-slide", true);
    itemSlide.setElementClass("active-options-right", true);
    item.setElementStyle("transform", "translate3d(-241px, 0px, 0px)");
}

public close(item: ItemSliding) {
    item.close();
    item.setElementClass("active-sliding", false);
    item.setElementClass("active-slide", false);
    item.setElementClass("active-options-right", false);
}
5 Likes
#10

how do i Make this happen in ionic 1

#11

This is great @Mxman06 . But I have one issue on close. Unlike swipe that automatically closes on tapping elsewhere within the slider, this one does not automatically close. Plus after my slider is swiped open(via code/manually) the components inside the slider become untappable, ie everything other than ion-item-option buttons are disabled. How do I close this open slider on tapping outside, on the non-enabled part?

#12

@Mxman06, @tspriyaa, @Danny_Bigdi, @fabiomalet, @kristofsw, @Jeremiah
Hi all, Just a sharing. Hope it helps others as well. I guess ionic 1 user also can refer to the similar approach.

What is happening in ionic? ionic actually add a gesture listener to the slider. and the listener calls the slider to change the UI accordingly.

I guess the approach of changing the CSS can simulate the effect but it is quite tricky if ionic changes it’s CSS class name…
Also the reason why it wont be able to hide the options automatically because of the gesture listener’s variable is null, therefore, it cannot “close” the slider.
Anyway, anyone who is interested in how it work, search for [item-sliding-guesture.js] and [item-sliding.js] for more detail.
I hope this can make a good start, looking for the experts enhance the implementation.

Ok, lets go straight to the Solutions…
in the html.

<ion-item-sliding #slidingItem (click)="close($event)">
        <ion-item #item>
          <button (click)=**"open(slidingItem, item, $event)"** *ngIf="editMode == true" item-left no-border ion-button color="danger" round clear icon-only>
            <ion-icon name='remove-circle'></ion-icon>
          </button>
          <ion-avatar item-left>
            <img src="img/marty-avatar.png">
          </ion-avatar>
          <button >
            M hero ok?
          </button>
        </ion-item>
        <ion-item-options side="right">
          <button icon-button style="background-color:red;color:white; font-weight:bold" (click)="removeItem()">
            Remove
          </button>
        </ion-item-options>
      </ion-item-sliding>

in the TS

public open(itemSlide: ItemSliding, item: Item, $event) {
itemSlide.startSliding(360); //any number can do
itemSlide.moveSliding(330); // any number small than the previous one
this.selectedItemSlide = itemSlide;
setTimeout(()=>{
itemSlide.moveSliding(320); // any number smaller than the previous one
itemSlide.endSliding(0.3); // you can mock anything less than 0.3
}, 100);
// the reason why i delay 0.1s, that is because i need to give sometime for the logic inside moveSliding to set a flag to false, in order to make it automatically slide.
}

public close($event) {
if (this.selectedItemSlide) {
this.selectedItemSlide.close();
}
}

#13

there is a much simpler solution :slight_smile:

itemSlide._setOpenAmount(100) ;

feel free to change the “100” to whatever you wish. it will open with the animation, and will conserve every feature baked inside. the number you provide is the number of pixel you want it to be opened ( a number that you have to chose according to the width of the sliding-buttons underneath the ion-item :smiley:

2 Likes
#14

Hi iliasbhal,

That is a nice solution, not sure if I have a older version or if they changed eventually.

_setOpenAmount is a private method now;
private _setOpenAmount(openAmount, isFinal);

#15

Hi guys,

i use ideas from @hpwah @fabiomalet posts and here fully working/tested

My ionic info

@ionic/app-scripts              : 1.3.7
@ionic/cli-plugin-cordova       : 1.0.0
@ionic/cli-plugin-ionic-angular : 1.0.0
Ionic Framework                 : ionic-angular 3.1.1

My solution

1 Like
#16

@ihsanberahim, tks a lot! i’ll give it a try and let you know! :smiley:

#17

What about keeping the same behaviour and animations as if you were sliding?


openSlide(itemSlide: ItemSliding, item: Item) {
// Keep track of the last item slided so i can duplicate behaviour when another is being opened
    if(this.lastItemSliding){
      if(this.lastItemSliding.item['opened']){
        this.closeSlide(this.lastItemSliding);
      }
    }
    let eleRef =itemSlide.item.getElementRef();
//Get number of siblings buttons in ion-options to calculate the width to slide
    let options = eleRef.nativeElement['nextElementSibling']['children'].length;
    itemSlide.item['opened'] = true;
    itemSlide.setElementClass("active-sliding", true);
    itemSlide.setElementClass("active-slide", true);
    itemSlide.setElementClass("active-options-right", true);
    this.lastItemSliding = itemSlide;
// I used a FIXED width for ion-options buttons. Siblings Width can be used
    item.setElementStyle("transform", `translate3d(-${options*70}px, 0px, 0px)`);

  }
// I added a <button> in <ion-options> to close the slide, as the item doesn't trigger events when opened
  closeSlide(itemSlide: ItemSliding) {
    itemSlide.item['opened'] = false;
    itemSlide.close();
    setTimeout(()=>{
      itemSlide.setElementClass("active-slide", false);
      itemSlide.setElementClass("active-sliding", false);
      itemSlide.setElementClass("active-options-right", false);
    },600);
  }
#18

remove type in your param function

#19

I had issues with this and came up with another possible solution.

clickSlide(itemSlide: ItemSliding) {    
    if (itemSlide.getSlidingPercent() == 0) {
      // Two calls intentional after examination of vendor.js function
      itemSlide.moveSliding(-1000);
      itemSlide.moveSliding(-1000);      
    }
    else {
      itemSlide.close();
    }    
  }

The moveSliding(amount: string) method calls _setOpenAmount as described by @iliasbhal

My ion-item slides from right to left so the amount needed to be negative. Any value beyond the max slide amount should work.

The call is made twice because moveSliding has a check at the beginning that will return the first time it is called, but the second time it will pass and reach the _setOpenAmount call.

and my template:

<ion-list>
    <ion-item-sliding #slidingItem *ngFor="let thing of things| async">    
      <ion-item #item detail-push (click)="clickSlide(slidingItem)" >
        {{thing.text}}        
      </ion-item>
      <ion-item-options side="right" (click)="clickSlide(slidingItem)">
        <button ion-button color="primary" (click)="actionTapped($event, thing)">
          <ion-icon name="open"></ion-icon>
          Action
        </button>
      </ion-item-options>     
    </ion-item-sliding>
  </ion-list>
1 Like
#20

Awsome.
But this needs additional code in case users still use sliding gesture.
Use IonDrag.

<ion-item-sliding #slidingItem (ionDrag)=“onSlide(slidingItem)”

onSlide(slidingItem: ItemSliding){
    console.log('Drag activated. closing item slide..'); 
    if(this.activeItemSliding) {
      this.activeItemSliding.close();
      this.activeItemSliding = null;
     }
   }
#21

Not sure if it helps, but Josh Morony has a nice tutorial on item sliding animation