https://www.loom.com/share/d0b06359b5e84073b944340ca4fba617?sharedAppSource=personal_library
An example is written in Vue 3 Shopify draggable emits wrong indexes on sort finished(watch loom video)
function dragEnd(event: SortableStopEvent): void {
console.log(event.oldIndex, event.newIndex)
// store.dispatch('tasksModule/changeTaskOrder', {newOrder: event.newIndex, taskId})
}
<template>
<ul ref="root">
<slot></slot>
</ul>
</template>
<script lang="ts" setup>
import { Sortable, Plugins, SortableStopEvent, SortableStartEvent } from '@shopify/draggable'
import { onMounted, ref } from 'vue'
interface Props {
handleSelector: string
draggedElement: string
}
const props = withDefaults(defineProps<Props>(), {
handleSelector: 'li',
draggedElement: 'li'
})
const root = ref<HTMLElement>()
const emit = defineEmits<{
(e: 'dragStart', value: SortableStartEvent): void
(e: 'dragEnd', value: SortableStopEvent): void
}>()
onMounted(() => {
const sortable = new Sortable(root.value, {
draggable: props.draggedElement,
handle: props.handleSelector,
plugins: [Plugins.SwapAnimation],
sortAnimation: {
duration: 200,
easingFunction: 'ease-in-out'
},
mirror: {
xAxis: false,
cursorOffsetX: 5,
constrainDimensions: true
}
})
sortable.on('sortable:stop', (event: SortableStopEvent) => emit('dragEnd', event))
sortable.on('sortable:start', (event: SortableStartEvent) => emit('dragStart', event))
})
</script>
<style scoped lang="scss">
</style>
<Sortable class="todo__list" @dragEnd="dragEnd" handleSelector=".todo-item__drag">
<li class="todo__item" v-for="task in tasks" :key="task.id">
<div class="todo__item-overlay"></div>
<AppTodoItem is-draggable @delete="deleteTask" :todoitem="task"></AppTodoItem>
</li>
</Sortable>
onMounted(async () => {
await store.dispatch('tasksModule/fetchTasks')
})
const tasks = computed<Task[]>(() => {
return store.getters['tasksModule/tasks']
})