Vue Draggable
Vue Draggable is a lightweight, dependency-free drag and drop library specifically designed for Vue.js applications. It leverages native HTML5 drag and drop APIs, making it a performant choice for reordering lists or moving items between zones. The current stable version is 2.0.6, and it primarily targets Vue 2.x environments. Its key differentiators include its complete lack of external dependencies, offering a lean footprint, and providing flexible integration options as a global plugin, a local directive, or an optional renderless component (`VueDraggableGroup`) for advanced reactivity management. While it does not specify a strict release cadence, updates are generally aligned with maintaining compatibility and addressing issues within the Vue 2 ecosystem.
Common errors
-
TypeError: Cannot read properties of undefined (reading 'use')
cause Attempting to use `Vue.use(VueDraggable)` in a Vue 3 environment, where the global `Vue` instance and plugin API have changed significantly.fixThis library is not compatible with Vue 3. Migrate to a Vue 3 compatible drag and drop solution or downgrade your Vue version to 2.x. -
Failed to resolve directive: drag-and-drop
cause The `v-drag-and-drop` directive has not been properly registered, either globally via `Vue.use(VueDraggable)` or locally in the component's `directives` option.fixEnsure `Vue.use(VueDraggable)` is called once at your application's entry point, or if registering locally, `import { VueDraggableDirective } from 'vue-draggable'` and include it in `directives: { dragAndDrop: VueDraggableDirective }` within your component options. -
Items are not visually reordering or data model is not updating correctly after a drag-and-drop operation.
cause Manual data manipulation for reordering/moving items is not implemented, or the `reactivityEnabled` option is set to `false`, or `VueDraggableGroup` is not used for reactive data structures.fixFor reactive data, consider using the `VueDraggableGroup` renderless component. If handling manually, ensure `reactivityEnabled: true` in your options and implement logic within `onDrop`, `@added`, `@removed`, or `@reordered` events to update your underlying data arrays.
Warnings
- breaking This library is designed for Vue 2.x and is not compatible with Vue 3. Using it with Vue 3 will lead to runtime errors, particularly with `Vue.use()` or directive registration.
- gotcha When utilizing the custom dropzone events (@added, @removed, @reordered), ensure that your draggable list items (e.g., `<li>` elements) have a `data-id` attribute defined. Without this, the event payload's `ids` array will be empty.
- gotcha The `VueDraggableGroup` renderless component, which provides built-in reactivity handling for drag-and-drop operations, requires Vue.js version 2.6.0 or higher. Using it with older Vue 2 versions might result in unexpected behavior or errors.
Install
-
npm install vue-draggable -
yarn add vue-draggable -
pnpm add vue-draggable
Imports
- VueDraggable
import { VueDraggable } from 'vue-draggable'import VueDraggable from 'vue-draggable'
- VueDraggableDirective
import VueDraggableDirective from 'vue-draggable'
import { VueDraggableDirective } from 'vue-draggable' - VueDraggableGroup
import VueDraggableGroup from 'vue-draggable'
import { VueDraggableGroup } from 'vue-draggable'
Quickstart
import Vue from 'vue';
import VueDraggable from 'vue-draggable';
Vue.use(VueDraggable);
new Vue({
el: '#app',
template: `
<div id="app">
<h3>My Drag & Drop Lists</h3>
<div v-drag-and-drop:options="options">
<ul @added="onAdded" @removed="onRemoved" @reordered="onReordered">
<li v-for="item in items1" :key="item.id" :data-id="item.id">{{ item.name }}</li>
</ul>
<ul @added="onAdded" @removed="onRemoved" @reordered="onReordered">
<li v-for="item in items2" :key="item.id" :data-id="item.id">{{ item.name }}</li>
</ul>
</div>
</div>
`,
data() {
return {
items1: [
{ id: 1, name: 'Task A' },
{ id: 2, name: 'Task B' }
],
items2: [
{ id: 3, name: 'Task X' },
{ id: 4, name: 'Task Y' }
],
options: {
dropzoneSelector: 'ul',
draggableSelector: 'li',
multipleDropzonesItemsDraggingEnabled: true,
onDrop: (event) => {
console.log('Item dropped:', event.items.map(i => i.dataset.id));
// For simple scenarios, manual data manipulation would go here.
// For reactive data, VueDraggableGroup is recommended.
}
}
};
},
methods: {
onAdded({ ids, index, dropzone }) {
console.log('Item added:', ids, 'at index:', index, 'in dropzone:', dropzone);
// Update your data model based on these events
},
onRemoved({ ids, index, dropzone }) {
console.log('Item removed:', ids, 'from index:', index, 'in dropzone:', dropzone);
},
onReordered({ ids, index, dropzone }) {
console.log('Item reordered:', ids, 'at index:', index, 'in dropzone:', dropzone);
}
}
});