Vue.js Drag and Drop Wrapper

raw JSON →
1.3.1 verified Sat Apr 25 auth: no javascript abandoned

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.

error Error in render: 'key' is missing for v-for on element <div class="item">
cause Vue.js warning/error indicating that elements within a `v-for` loop lack a unique `:key` attribute, which is especially problematic in draggable lists for DOM reconciliation.
fix
Add a unique :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')
cause Attempting to access `Vue.vueDragula.eventBus` or other plugin APIs before `vue-dragula` has been properly installed via `Vue.use()`.
fix
Ensure 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
cause The `vue-dragula` package was not correctly imported or made globally available in the application's scope.
fix
If using CommonJS, ensure 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.
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.
fix For Vue 3, consider alternative libraries like VueDraggable (based on Sortable.js) or implement drag-and-drop directly with native browser APIs or other Vue 3 compatible solutions.
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.
fix Consider migrating to a actively maintained drag-and-drop library for Vue to ensure ongoing compatibility, bug fixes, and security updates.
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.
fix Ensure all `v-for` iterations within `v-dragula` containers have a unique `:key` binding, e.g., `:key="item.id"` for objects or `:key="item"` for plain strings/numbers.
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.
fix If encountering `2.0.0-alpha.1` specific issues, revert to `1.x.x` for stability, or update code to reflect the new plugin name (`Vue.dragula` or `this.$dragula`) and handle model updates manually based on `eventBus` events.
npm install vue-dragula
yarn add vue-dragula
pnpm add vue-dragula

This quickstart demonstrates how to install `vue-dragula` in a Vue 2 application, set up two drag-and-drop containers with a shared bag, configure bag-specific options, and listen for the `dropModel` event to react to model changes and log them to the console.

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>
*/