{"id":12581,"library":"vue-smooth-dnd","title":"Vue Smooth DnD","description":"Vue Smooth DnD is a lightweight and performant Vue.js wrapper library for the underlying `smooth-dnd` core library. Currently at version 0.8.1, it provides comprehensive drag-and-drop and sortable functionalities for Vue applications. The library exposes Vue components like `Container` and `Draggable`, which allow developers to easily implement interactive UIs with features such as vertical or horizontal orientation, different drag behaviors (move, copy, drop-zone), drag handles, and auto-scrolling. While a specific release cadence isn't detailed, its evolution is closely tied to the `smooth-dnd` project. It stands out by offering a highly configurable, efficient solution, making it suitable for a wide array of user interaction requirements within the Vue ecosystem.","status":"active","version":"0.8.1","language":"javascript","source_language":"en","source_url":"https://github.com/kutlugsahin/vue-smooth-dnd","tags":["javascript","Vue","Vue.js","sortable","drag and drop","drag&drop","drag","drop","draggable"],"install":[{"cmd":"npm install vue-smooth-dnd","lang":"bash","label":"npm"},{"cmd":"yarn add vue-smooth-dnd","lang":"bash","label":"yarn"},{"cmd":"pnpm add vue-smooth-dnd","lang":"bash","label":"pnpm"}],"dependencies":[{"reason":"Core drag and drop logic is provided by this library, vue-smooth-dnd is a wrapper.","package":"smooth-dnd","optional":false}],"imports":[{"note":"Container is a named export, not a default export.","wrong":"import Container from 'vue-smooth-dnd';","symbol":"Container","correct":"import { Container } from 'vue-smooth-dnd';"},{"note":"Primarily designed for ESM usage in Vue applications; CJS require is less common but possible in some build setups.","wrong":"const { Draggable } = require('vue-smooth-dnd');","symbol":"Draggable","correct":"import { Draggable } from 'vue-smooth-dnd';"},{"note":"It is generally recommended to use named imports for tree-shaking and clarity, rather than importing the entire module namespace.","wrong":"import * as Components from 'vue-smooth-dnd';","symbol":"Container, Draggable","correct":"import { Container, Draggable } from 'vue-smooth-dnd';"}],"quickstart":{"code":"<template>\n  <div>\n    <div class=\"simple-page\">\n        <Container @drop=\"onDrop\">            \n          <Draggable v-for=\"item in items\" :key=\"item.id\">\n            <div class=\"draggable-item\">\n              {{item.data}}\n            </div>\n          </Draggable>\n        </Container>\n    </div>\n  </div>\n</template>\n\n<script lang=\"ts\">\nimport { Container, Draggable } from \"vue-smooth-dnd\";\n// Assume applyDrag and generateItems are utility functions provided by the user or an example\n// For a runnable example, we'll define simple versions.\n\nfunction applyDrag(arr: any[], dragResult: any) {\n  const { removedIndex, addedIndex, payload } = dragResult;\n  if (removedIndex === null && addedIndex === null) return arr;\n\n  const result = [...arr];\n  let itemToAdd = payload;\n\n  if (removedIndex !== null) {\n    itemToAdd = result.splice(removedIndex, 1)[0];\n  }\n\n  if (addedIndex !== null) {\n    result.splice(addedIndex, 0, itemToAdd);\n  }\n\n  return result;\n}\n\nfunction generateItems(count: number, creator: (index: number) => any) {\n  const result = [];\n  for (let i = 0; i < count; i++) {\n    result.push(creator(i));\n  }\n  return result;\n}\n\nexport default {\n  name: \"SimpleDnD\",\n  components: { Container, Draggable },\n  data() {\n    return {\n      items: generateItems(5, i => ({ id: i, data: \"Draggable \" + i }))\n    };\n  },\n  methods: {  \n    onDrop(dropResult: any) {\n      this.items = applyDrag(this.items, dropResult);\n    }\n  }\n};\n</script>\n\n<style>\n.draggable-item {\n  padding: 10px;\n  margin-bottom: 5px;\n  background-color: #f0f0f0;\n  border: 1px solid #ccc;\n  cursor: grab;\n}\n.simple-page {\n  width: 300px;\n  border: 1px dashed #eee;\n  padding: 10px;\n}\n</style>","lang":"typescript","description":"This quickstart demonstrates a basic sortable list using `Container` and `Draggable` components, handling drops with the `onDrop` event and a utility `applyDrag` function to update the item order."},"warnings":[{"fix":"Always bind an `@drop` listener to the `Container` and manually update the `items` array in your component's data or state management store using the `dropResult`.","message":"The `onDrop` event emitted by the `Container` component provides `dropResult` but does not automatically modify your data array. You must implement logic (like the provided `applyDrag` helper) to update your component's state based on `removedIndex`, `addedIndex`, and `payload`.","severity":"gotcha","affected_versions":">=0.1.0"},{"fix":"Ensure that every element or component you want to be draggable inside a `Container` is nested directly inside a `<Draggable>` tag, e.g., `<Container><Draggable><div>Item</div></Draggable></Container>`.","message":"All direct children of a `Container` component intended to be draggable must be explicitly wrapped within a `<Draggable>` component. Failing to do so will prevent items from being draggable or cause unexpected rendering issues.","severity":"gotcha","affected_versions":">=0.1.0"},{"fix":"Add `:group-name=\"'my-group'\"` to all `Container` components that should allow items to be moved between them. You can also customize this behavior with the `shouldAcceptDrop` prop.","message":"For drag-and-drop operations between multiple `Container` components, you must assign the same `group-name` prop to all containers that should participate in the group. If `group-name` is not set, a container will not accept drags from outside its own instance.","severity":"gotcha","affected_versions":">=0.1.0"},{"fix":"If you need to render the `Container` as a specific HTML element or with additional attributes, use the `tag` prop. For complex cases, provide an object: `:tag=\"{value: 'table', props: {class: 'my-table'}}\"`.","message":"The `tag` property for the `Container` component can accept either a `string` (e.g., `'div'`, `'ul'`) or an `object` with `value` and `props` (e.g., `{ value: 'table', props: { class: 'my-table' } }`). Misunderstanding this can lead to incorrect root element rendering.","severity":"gotcha","affected_versions":">=0.1.0"}],"env_vars":null,"last_verified":"2026-04-19T00:00:00.000Z","next_check":"2026-07-18T00:00:00.000Z","problems":[{"fix":"Verify that the `@drop` event is correctly bound to the `Container` component and that the `onDrop` method receives the `dropResult` object as its argument. Ensure `dropResult` is not accidentally reassigned or ignored.","cause":"The `onDrop` event handler is attempting to access properties of `dropResult` (e.g., `removedIndex`, `addedIndex`) but `dropResult` is undefined or not an object due to an incorrect event binding or prop usage.","error":"TypeError: Cannot read properties of undefined (reading 'removedIndex')"},{"fix":"Ensure your `onDrop` method correctly processes the `dropResult` by using a utility like `applyDrag` to create a *new* array with the updated order/content and assigns it back to your reactive `items` data property (`this.items = newItemsArray`). Direct mutation of the original array might not trigger reactivity in some Vue versions or setups.","cause":"The component's internal `items` array is not being updated correctly after a drop operation, likely because the `onDrop` event handler is missing or incorrectly implemented.","error":"Items do not move or reorder when dragged, or disappear after dropping."},{"fix":"Ensure you have `import { Container, Draggable } from 'vue-smooth-dnd';` at the top of your script, and that both `Container` and `Draggable` are listed in the `components` option of your Vue component: `components: { Container, Draggable }`.","cause":"The `Draggable` component (or `Container`) has not been correctly imported or registered within the Vue component where it's being used.","error":"console.warn: [Vue warn]: Failed to resolve component: draggable"}],"ecosystem":"npm"}