Vue Drag and Drop Wrapper
vue-drag-drop is a lightweight Vue wrapper designed to simplify the often "wonky" native HTML Drag and Drop API. It aims to abstract away common pitfalls, such as the inability to access transferred data during `dragover` events, the need to manually serialize complex data types like objects and arrays, and the requirement for `event.preventDefault()` on drop zones. The current stable version is 1.1.4. While it does not specify a strict release cadence, updates have occurred since its major 1.0.0 release, which introduced significant changes. Key differentiators include its focus on simplicity and a minimal API, contrasting with more comprehensive drag-and-drop solutions that often include list reordering or extensive UI features. It is specifically built for Vue 2 applications and ships with TypeScript type definitions.
Common errors
-
Property 'transferData' does not exist on type 'DragEvent'
cause Attempting to access `event.dataTransfer` directly within a custom drag/drop handler after version 1.0.0, which no longer uses this for internal data transfer.fixAccess the transferred data directly from the first argument of `vue-drag-drop`'s custom event handlers (e.g., `onDrop(data, event) { /* use data */ }`). The `transfer-data` prop is automatically made available here. -
[Vue warn]: Unknown custom element: <drag> - did you register the component correctly?
cause The `<Drag>` or `<Drop>` component has not been correctly registered in your Vue application, or Vue is not properly configured to recognize custom elements.fixEnsure you have either called `Vue.use(VueDragDrop)` globally or individually registered `Drag` and `Drop` components using `Vue.component('drag', Drag)` and `Vue.component('drop', Drop)` within your component's `components` option. -
TypeError: Cannot read properties of undefined (reading 'Drag')
cause This typically occurs in a browser environment when `vue-drag-drop.browser.js` is loaded, but Vue itself is not yet available globally, or if you're trying to access `VueDragDrop.Drag` before the script has properly executed.fixEnsure that `vue.js` (or `vue.min.js`) is loaded *before* `vue-drag-drop.browser.js` in your HTML `<script>` tags, or if using a module bundler, ensure proper import order and configuration.
Warnings
- breaking Beginning with version 1.0.0, `vue-drag-drop` no longer relies on the native `event.dataTransfer` property for cross-browser compatibility, especially for IE/Edge. Instead, it uses a global variable to manage drag transfer information. While designed to be robust, this change could theoretically impact extreme edge cases involving simultaneous drag events.
- gotcha This library is designed for Vue 2 applications, as indicated by the `vue-2.x` badge in its documentation. It is not compatible with Vue 3 and will likely lead to errors if used in a Vue 3 project due to breaking changes in Vue's API.
- gotcha While `vue-drag-drop` simplifies the browser's Drag and Drop API, it is primarily intended for simple data transfer between a draggable and a dropzone. It is not a comprehensive solution for complex list reordering, sorting, or multi-item dragging scenarios, which typically require more specialized libraries.
Install
-
npm install vue-drag-drop -
yarn add vue-drag-drop -
pnpm add vue-drag-drop
Imports
- Drag, Drop
import Drag from 'vue-drag-drop'; // Incorrectly importing a named export as default const { Drag, Drop } = require('vue-drag-drop'); // CommonJS require in modern Vue projects using bundlersimport { Drag, Drop } from 'vue-drag-drop'; - VueDragDrop (plugin)
import { VueDragDrop } from 'vue-drag-drop'; // Incorrectly importing a default export as namedimport VueDragDrop from 'vue-drag-drop';
- VueDragDrop (browser global)
import VueDragDrop from './node_modules/vue-drag-drop/dist/vue-drag-drop.browser.js'; // Incorrect import path for browser global; typically used via script tag
// Include via <script src="vue-drag-drop/dist/vue-drag-drop.browser.js"></script> // Then access: Vue.component('drag', VueDragDrop.Drag)
Quickstart
<template>
<div id="app">
<h1>Vue Drag Drop Basic Demo</h1>
<div style="display: flex; gap: 20px; justify-content: center;">
<drag
:transfer-data="{ type: 'file', name: 'document.pdf', size: '1.2MB' }"
effect-allowed="copy"
class="drag-item"
>
<span>Draggable File</span>
</drag>
<drop
@drop="onDrop"
@dragenter="onDragEnter"
@dragleave="onDragLeave"
@dragover.prevent
class="drop-zone"
:class="{ 'drag-over': isDragOver }"
>
<p>{{ dropMessage }}</p>
<p v-if="droppedData">File: {{ droppedData.name }} ({{ droppedData.size }})</p>
</drop>
</div>
</div>
</template>
<script lang="ts">
import Vue from 'vue';
import { Drag, Drop } from 'vue-drag-drop';
export default Vue.extend({
components: { Drag, Drop },
data() {
return {
droppedData: null as { type: string; name: string; size: string } | null,
dropMessage: 'Drop files here!',
isDragOver: false,
};
},
methods: {
onDrop(data: any) {
this.droppedData = data;
this.dropMessage = `Dropped ${data.name}!`;
this.isDragOver = false;
console.log('Dropped data:', data);
},
onDragEnter() {
this.isDragOver = true;
this.dropMessage = 'Release to drop...';
},
onDragLeave() {
this.isDragOver = false;
this.dropMessage = 'Drop files here!';
},
},
});
</script>
<style scoped>
.drag-item { padding: 15px 25px; background-color: #42b983; color: white; border-radius: 5px; cursor: grab; }
.drop-zone { padding: 30px; border: 2px dashed #ccc; border-radius: 5px; min-width: 250px; text-align: center; }
.drop-zone.drag-over { border-color: #42b983; background-color: #e6ffe6; }
</style>