Vue Draggable Plus
Vue Draggable Plus is a universal drag-and-drop component library supporting both Vue 3 and Vue 2.7+ applications, building upon the capabilities of Sortablejs. The current stable version is 0.6.1, with an active release cadence reflecting ongoing development and maintenance. It addresses a gap where the official Sortablejs Vue components had become out of sync with modern Vue 3 practices. A key differentiator is its flexibility, offering multiple usage patterns including a component, a Composition API composable (`useDraggable`), and a directive (`v-draggable`). It uniquely solves the problem of integrating drag-and-drop with complex component libraries by allowing developers to specify any element as the drag container using a selector, overcoming limitations of previous implementations that required the component itself to be the direct list child. The library ships with comprehensive TypeScript types.
Common errors
-
Property 'Options' does not exist on type 'typeof import("vue-draggable-plus")'.cause Attempting to import or use TypeScript types (like `Options` or `SortableEvent`) directly from `vue-draggable-plus` in versions prior to 0.4.1, where they were not correctly exported or defined.fixUpgrade `vue-draggable-plus` to version `0.4.1` or newer. For `SortableEvent` and other core Sortablejs types, import them directly from `sortablejs` (e.g., `import type { SortableEvent } from 'sortablejs';`). -
Data does not update when adding or removing items from a `v-model` bound list after a drag operation.
cause A bug in `vue-draggable-plus` versions prior to 0.5.0 prevented the `update:model-value` event from firing correctly when items were added or removed, only handling reordering.fixUpdate `vue-draggable-plus` to version `0.5.0` or newer. If stuck on an older version, manually update your data array based on the `onAdd` or `onRemove` events. -
The `onMove` callback function is not preventing items from being dragged, even when it returns `false`.
cause A defect in `vue-draggable-plus` versions prior to 0.5.3 caused the return value of the `onMove` callback to be ignored, failing to prevent the element from being dragged.fixUpgrade `vue-draggable-plus` to version `0.5.3` or newer.
Warnings
- gotcha Prior to version 0.5.0, the `v-model` (which uses `update:model-value`) might not have correctly triggered updates when items were added or removed from the draggable list, potentially leading to out-of-sync data in your application state.
- gotcha In TypeScript projects, obtaining correct types for `Sortablejs` options (e.g., `Options`) and events (e.g., `SortableEvent`) directly from `vue-draggable-plus` was problematic in older versions, leading to type errors or needing workarounds.
- gotcha The `onMove` callback, which allows you to prevent dragging of specific items by returning `false`, did not function correctly in versions prior to 0.5.3, meaning it was impossible to programmatically stop a drag action.
Install
-
npm install vue-draggable-plus -
yarn add vue-draggable-plus -
pnpm add vue-draggable-plus
Imports
- VueDraggable
const VueDraggable = require('vue-draggable-plus').VueDraggableimport { VueDraggable } from 'vue-draggable-plus' - useDraggable
import VueDraggable from 'vue-draggable-plus'
import { useDraggable } from 'vue-draggable-plus' - vDraggable
import { Draggable } from 'vue-draggable-plus'import { vDraggable } from 'vue-draggable-plus' - SortableEvent
import type { SortableEvent } from 'vue-draggable-plus'import type { SortableEvent } from 'sortablejs'
Quickstart
```typescript
<template>
<div ref="el" class="drag-container">
<div v-for="item in list" :key="item.id" class="drag-item">
{{ item.name }}
</div>
</div>
</template>
<script setup lang="ts">
import { ref, onMounted } from 'vue'
import { useDraggable } from 'vue-draggable-plus'
interface ListItem {
name: string;
id: number;
}
const el = ref<HTMLElement | null>(null)
const list = ref<ListItem[]>([
{ name: 'Item A', id: 1 },
{ name: 'Item B', id: 2 },
{ name: 'Item C', id: 3 },
{ name: 'Item D', id: 4 }
])
const draggable = useDraggable(el, list, {
animation: 150,
onStart() {
console.log('Drag started')
},
onEnd(event) {
console.log('Drag ended:', event.oldIndex, '->', event.newIndex)
// The list.value is automatically updated by useDraggable
}
})
onMounted(() => {
// For demonstration, you could programmatically start/destroy draggable if needed
// console.log('Draggable instance:', draggable)
})
</script>
<style>
.drag-container {
border: 1px solid #eee;
padding: 10px;
min-height: 100px;
}
.drag-item {
padding: 8px 12px;
margin-bottom: 5px;
background-color: #f9f9f9;
border: 1px solid #ddd;
cursor: grab;
}
.drag-item:hover {
background-color: #f0f0f0;
}
</style>
```