How to programatically close ion-sliding-item?

I have a component below which renders information for each element in the list:

<template>
  <ion-item-sliding>
    <ion-item-options side="start">
      <ion-item-option color="danger">
        <ion-icon :icon="trashOutline" slot="icon-only"></ion-icon>
      </ion-item-option>
    </ion-item-options>
    <ion-item lines="full" color="secondary">
      <ion-icon
        :src="require(`@/static/icons/categories.svg`)"
        slot="start"
      ></ion-icon>
      <ion-label>{{ category.name }}</ion-label>
    </ion-item>
    <ion-item-options side="end">
      <ion-item-option @click="editCategory(category.id)">
        <ion-icon :icon="create" slot="icon-only"></ion-icon>
      </ion-item-option>
    </ion-item-options>
  </ion-item-sliding>
</template>

<script>
  import { useRouter } from 'vue-router'
  import { trashOutline, create } from 'ionicons/icons'
  export default {
    name: 'CategoryListItem',
    props: {
      category: {
        type: Object,
        required: true,
      },
    },
    setup() {
      const router = useRouter()

      const editCategory = async (categoryId) => {
        await router.push(`/categories/edit/${categoryId}`)
      }

      return {
        trashOutline,
        create,
        editCategory,
      }
    },
  }
</script>

In this component I have ion-item-sliding component rendering the information. The ion-label inside the ion-item-sliding has option of Delete to the left and the option of Edit to the right. Now, what I would like to do is reset or close the ion-item-sliding element with the close() function after the Edit or Delete function is pressed. I tried to close it with ref, but I was unsuccessful (ref pointing to the ion-item-sliding component). Request anyone to please help me in closing the ion-item-sliding programatically after I have routed ahead to the edit page in editCategory function.

@ldebeasi Can you please help me in this?

get a ref to the element using ref and then call the appropriate method - https://ionicframework.com/docs/api/item-sliding

I have found that doing a closeSlidingItems on the list containing the elements is more effective. https://ionicframework.com/docs/api/list

1 Like

@aaronksaunders Thanks for the reply.

So, what I have attempted is as given below:

Parent Component:

<template>
  <ion-list class="ion-no-padding" ref="categoryListRef">
    <category-list-item
      v-for="category in categories"
      :key="category.id"
      :category="category"
      @onDelete="resetSlides"
    />
  </ion-list>
</template>

<script>
  import { ref } from 'vue'
  import CategoryListItem from '@/components/categories/CategoryListItem.vue'
  export default {
    name: 'CategoryList',
    props: {
      categories: {
        type: Array,
        required: true,
      },
    },
    components: {
      CategoryListItem,
    },
    setup() {
      const categoryListRef = ref(null)
      const resetSlides = () => {
        categoryListRef.value.closeSlidingItems()
      }

      return {
        resetSlides,
        categoryListRef,
      }
    },
  }
</script>

<style scoped></style>

Child Component (CategoryListItem.vue):

<template>
  <ion-item-sliding ref="slidingRef">
    <ion-item-options side="start">
      <ion-item-option color="danger">
        <ion-icon :icon="trashOutline" slot="icon-only" />
      </ion-item-option>
    </ion-item-options>
    <ion-item lines="full" color="secondary">
      <ion-icon :src="require(`@/static/icons/categories.svg`)" slot="start" />
      <ion-label>{{ category.name }}</ion-label>
    </ion-item>
    <ion-item-options side="end">
      <ion-item-option @click="editCategory(category.id)">
        <ion-icon :src="require(`@/static/icons/edit.svg`)" slot="icon-only" />
      </ion-item-option>
    </ion-item-options>
  </ion-item-sliding>
</template>

<script>
  import { useRouter } from 'vue-router'
  import { trashOutline, create } from 'ionicons/icons'
  export default {
    name: 'CategoryListItem',
    props: {
      category: {
        type: Object,
        required: true,
      },
    },
    setup(_, { emit }) {
      const router = useRouter()

      const editCategory = async (categoryId) => {
        await router.push(`/categories/edit/${categoryId}`)
        emit('onDelete')
      }

      return {
        trashOutline,
        create,
        editCategory,
      }
    },
  }
</script>

<style scoped></style>

As you can see, in the parent component, I am already getting the ref for ion-list and I am calling categoryListRef.value.closeSlidingItems on the onDelete function emitted by the Child Component. But, I gett an error in the console like this:

Can you please suggest a solution to this?

I need to document this better, but you need to do categoryListRef.value.$el.closeSlidingItems(). Due to limitations in Vue, it’s not currently possible to forward your ref to the underlying Web Component, which is where the method is defined. By using $el, you can access the Web Component instance.

6 Likes

I added a Troubleshooting guide to the Ionic Vue docs that covers this (and other issues): https://ionicframework.com/docs/vue/troubleshooting You might need to do a hard refresh to see it.

edit: This is also covered in the quickstart guide now: https://ionicframework.com/docs/vue/quickstart#calling-methods-on-components

5 Likes

@ldebeasi Thanks a lot for this…

@iDevIonic0 @noopurphalak
I’m trying to do this as well but I got this error

Can you share your solution pls. Thanks
(a)Method selecting an item

const selectedCategory = (itemArray: string) => {
            
            const array = category.value
            const index = array.indexOf(itemArray);
            if (index > -1) array.splice(index, 1);
            closeSlidingItemRef.value.$el.closeSlidingItems()
            
        }

(b)Setting up ref

const closeSlidingItemRef = ref(null)

(c)HTML structure

<ion-list lines="none" >
                    <ion-item-sliding  ref="closeSlidingItemRef" v-for ="(item, index) in category" :key="index">
                        <ion-item text-wrap text-center style="font-size: .8rem" class="ion-no-padding">
                            <ion-label>{{item}}</ion-label>
                        </ion-item>
                        <ion-item-options side="end" >
                            <ion-item-option  @click="selectedCategory(item)" color="danger" class="ion-no-padding">
                                <ion-icon :icon="trash"></ion-icon>
                            </ion-item-option>
                        </ion-item-options>
                    </ion-item-sliding>
                </ion-list>