vue-smooth-dnd

repository·master·Indexed 23 days ago

https://github.com/kutlugsahin/vue-smooth-dnd

A fast, lightweight drag-and-drop and sortable library for Vue.js that acts as a wrapper around the smooth-dnd library. It provides highly configurable Container and Draggable components to implement various drag-and-drop scenarios, including support for custom payloads, drop target validation, and lifecycle events like @drag-start, @drag-enter, and @drop.

Tokens
3.6K
Snippets
7
Records
15
Agent score
33%

What's inside vue-smooth-dnd

  1. Understand the Drag Lifecycle

    master

    The drag lifecycle involves several stages, from initial click to final drop. Understanding this sequence is crucial for implementing custom logic via callbacks and events.

    Sequence Overview:

    1. Down: Initial click.
    2. Move: Initial drag starts.
      • get-child-payload() is called to retrieve the payload.
      • should-accept-drop() is called for all containers.
      • drag-start is fired for all containers.
      • drag-enter occurs as the item enters a container.
    3. Drag Over: Moving over containers.
      • drag-leave (as it leaves a container).
      • drag-enter (as it enters a container).
    4. Up: Finish drag.
      • should-animate-drop() is called for the target container.
      • drag-end is fired for all containers.
      • drop is fired only for droppable containers.

    Data Formats:

    • dragResult: { payload, isSource, willAcceptDrop }
    • dropResult: { addedIndex, removedIndex, payload, droppedElement }
  2. Basic Usage of Container and Draggable

    master

    To implement drag and drop, wrap your list of items in a Container component and wrap each individual item in a Draggable component. Use the @drop event on the Container to handle the state update when an item is moved.

    <template>
      <div>
        <div class="simple-page">
            <Container @drop="onDrop">
              <Draggable v-for="item in items" :key="item.id">
                <div class="draggable-item">
                  {{item.data}}
                </div
              </Draggable>
            </Container>
        </div
      </div>
    </template>
    
    <script>
    import { Container, Draggable } from "vue-smooth-dnd";
    import { applyDrag, generateItems } from "./utils";
    export default {
      name: "Simple",
      components: { Container, Draggable },
      data() {
        return {
          items: generateItems(50, i => ({ id: i, data: "Draggable " + i }))
        };
      },
      methods: {
      onDrop(dropResult) {
        this.items = applyDrag(this.items, dropResult);
      }
    };
    </script>
  3. Handle Container drag events

    master

    The Container component emits several events during the drag-and-drop lifecycle that allow you to execute custom logic.

    Lifecycle Events

    • @drag-start: Emitted by all containers when a drag begins.
    • @drag-end: Called by all containers when a drag ends (before the @drop event).
    • @drag-enter: Emitted by a container when a dragged item enters its boundaries.
    • @drag-leave: Emitted by a container when a dragged item leaves its boundaries.
    • @drop-ready: Called by the container being dragged over when the possible drop position index changes (e.g., when items slide to make space).
    • @drop: Emitted by relevant containers (the source and any container that could accept the drop) after the drop animation ends.

    Event Parameters

    Drag Result (@drag-start, @drag-end)

    Passed as an object containing:

    • payload: The object returned by get-child-payload(). Undefined if not set.
    • isSource: boolean. true if the event is from the container where the drag originated.
    • willAcceptDrop: boolean. true if the dragged item can be dropped into this container.

    Drop Result (@drop-ready, @drop)

    Passed as an object containing:

    • removedIndex: number. The index of the removed child (or null).
    • addedIndex: number. The index where the item is added (or null).
    • payload: The object returned by get-child-payload().
    • element / droppedElement: The DOMElement that was moved.
    // Example: Handling @drag-start
    <Container @drag-start="onDragStart">
    
    // Logic
    onDragStart (dragResult) {
      const { isSource, payload, willAcceptDrop } = dragResult
    }
    
    // Example: Handling @drop-ready
    <Container @drop-ready="onDropReady">
    
    // Logic
    onDropReady(dropResult) {
      const { removedIndex, addedIndex, payload, element } = dropResult;
    }
  4. Use `get-ghost-parent()` to fix positioning issues

    master

    The :get-ghost-parent callback allows you to specify which DOM element the dragged 'ghost' element should be appended to.

    When to use: By default, the ghost is appended to the container itself. However, if any ancestor of the container has a CSS transform property, the ghost's 'fixed' positioning will be relative to that ancestor, breaking calculations. In such cases, use this callback to return an element that does not have a transformed parent (e.g., document.body).

    ```jsx
    <Container :get-ghost-parent="getGhostParent">
    getGhostParent() {
      // i.e return document.body;
    }

    Returns: Element (The DOM element to append the ghost to).

  5. Use `get-child-payload()` to pass data to `onDrop`

    master

    Use the :get-child-payload callback to define a function that returns a custom payload object for a specific child item based on its index. This payload is then passed to the onDrop event.

    <Container :get-child-payload="getChildPayload">
    getChildPayload (index) {
      return {
        // generate custom payload data here
      }
    }
  6. Configure the Draggable tag property

    master

    The tag property on the Draggable component defines the root element rendered for the draggable item. It defaults to 'div'.

    You can provide:

    1. A string: The HTML tag name.
    2. An object: A Vue node definition containing value (the tag name) and props (an object of element properties).