Vue.js Drag and Drop Wrapper
raw JSON →Vue Dragula is a Vue.js wrapper for the popular Dragula library, providing simple drag-and-drop functionality primarily within Vue 2 applications. Its design allows for declarative drag-and-drop container setup using a custom `v-dragula` directive, integrating directly with Vue's data binding. The library exposes a global `Vue.vueDragula` API for setting bag-specific options, finding `drake` instances, and accessing an event bus for granular control over drag-and-drop events. This includes custom `dropModel` and `removeModel` events that expose `dropIndex` and `removeIndex` for easier model manipulation. The last stable release, 1.3.1, was in 2016 and primarily supports Vue 2.x. While a 2.0.0-alpha.1 version was released, it introduced significant breaking changes, indicated an unstable API, and the project appears to be no longer actively maintained, with no further stable releases or recent development activity.
Common errors
error Error in render: 'key' is missing for v-for on element <div class="item"> ↓
:key attribute to each element inside the v-for loop within a v-dragula container. For example, <div v-for="item in list" :key="item.id"> or <div v-for="text in list" :key="text">. error TypeError: Cannot read properties of undefined (reading 'eventBus') ↓
Vue.use(VueDragula) is called after vue and vue-dragula are loaded, typically at the application's entry point, before any Vue instances are created. error Error: "VueDragula" is not defined ↓
var VueDragula = require('vue-dragula'); is present. If using a direct script include, ensure the script tag for vue-dragula is after vue and dragula in your HTML. Warnings
breaking Vue Dragula is designed for Vue 2.x applications and is not compatible with Vue 3. Migration to Vue 3 would require finding an alternative drag-and-drop solution or a different wrapper. ↓
breaking The project appears to be abandoned. The last stable release was in 2016, and there has been no significant development since. This means no updates for newer Vue versions, bug fixes, or security patches. ↓
gotcha When using `v-for` directives inside `v-dragula` containers, it is critical to provide a unique `:key` prop to each iterated element. Failure to do so can lead to incorrect DOM updates and rendering issues after drag-and-drop operations. ↓
breaking Version 2.0.0-alpha.1 introduced significant breaking changes, including renaming the plugin from `Vue.vueDragula` to `Vue.dragula` and installing it to `vm.$dragula` on the instance. It also shifted to a one-way data flow, requiring manual model updates via the eventBus. This alpha was never stabilized. ↓
Install
npm install vue-dragula yarn add vue-dragula pnpm add vue-dragula Imports
- VueDragula wrong
import VueDragula from 'vue-dragula'; Vue.use(VueDragula);correctvar VueDragula = require('vue-dragula'); Vue.use(VueDragula); - Vue.vueDragula.options wrong
this.$dragula.options('my-bag', { direction: 'vertical' });correctVue.vueDragula.options('my-bag', { direction: 'vertical' }); - Vue.vueDragula.eventBus.$on wrong
this.$on('drop', ...);correctVue.vueDragula.eventBus.$on('drop', (args) => { console.log('drop: ' + args[0]); });
Quickstart
new Vue({
el: '#app',
data: {
colOne: ['Item 1.1', 'Item 1.2', 'Item 1.3'],
colTwo: ['Item 2.1', 'Item 2.2', 'Item 2.3']
},
methods: {
onClick(event) {
console.log('Clicked:', event.target.textContent);
}
},
created: function () {
// Set dragula options for 'first-bag' specifically
Vue.vueDragula.options('first-bag', {
direction: 'vertical',
removeOnSpill: true // Example option
});
// Listen for a custom vue-dragula event
Vue.vueDragula.eventBus.$on('dropModel', (bagName, el, target, source, dropIndex) => {
console.log(`Model dropped in ${bagName}: element ${el.textContent} at index ${dropIndex} in target ${target.className}`);
// Manually update your data model if necessary, as per v2 alpha notes, though v1 syncs automatically.
// Example: If dragging from colOne to colTwo
if (source.className.includes('col-one') && target.className.includes('col-two')) {
// This is simplified and assumes direct model manipulation, in reality, use appropriate array methods.
const movedItem = this.colOne.splice(el.dataset.originalIndex, 1)[0];
this.colTwo.splice(dropIndex, 0, movedItem);
} else if (source.className.includes('col-two') && target.className.includes('col-one')) {
const movedItem = this.colTwo.splice(el.dataset.originalIndex, 1)[0];
this.colOne.splice(dropIndex, 0, movedItem);
}
});
}
});
// Assuming a basic HTML structure and Vue/VueDragula are globally available
/*
<div id="app">
<div class="wrapper">
<div class="container col-one" v-dragula="colOne" bag="first-bag">
<div v-for="(text, index) in colOne" :key="text" @click="onClick" :data-original-index="index">{{text}} [click me]</div>
</div>
<div class="container col-two" v-dragula="colTwo" bag="first-bag">
<div v-for="(text, index) in colTwo" :key="text" :data-original-index="index">{{text}}</div>
</div>
</div>
</div>
*/