Skip to content

DOM element remains in source list when moving items between nested draggable instances #230

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
rendomnet opened this issue Feb 20, 2025 · 3 comments

Comments

@rendomnet
Copy link

Description

When moving an item from a root draggable to a nested draggable instance, the item appears in both places despite the data being updated correctly. This happens because the onRemove handler re-inserts the item into the source list before checking pullMode.

Current Behavior

  1. Move item from root draggable to nested draggable
  2. Item appears in both source and target lists
  3. Data updates correctly, but DOM doesn't reflect the change

Expected Behavior

When moving an item between draggable instances, the item should:

  1. Be removed from source list's DOM
  2. Appear only in target list
  3. Data and DOM should be in sync

Issue Location

In useDraggable.ts, the onRemove handler:

typescript
const defaultOptions = {
onRemove(evt: SortableEvent) {
const { from, item, oldIndex, oldDraggableIndex, pullMode, clone } = evt
insertNodeAt(from, item, oldIndex) // <-- This line causes the issue
if (pullMode === 'clone') {
removeNode(clone!)
return
}
// ... data update logic
}
}

The insertNodeAt(from, item, oldIndex) call re-inserts the item into the source list before checking pullMode, causing the item to remain in both places.

Reproduction

  1. Create two draggable instances (parent and nested)
  2. Configure with group="items"
  3. Try to move item from parent to nested draggable
  4. Observe item appears in both lists

Environment

  • vue-draggable-plus version: 6.0
  • Vue version: 3.x
@rendomnet
Copy link
Author

1.The issue is in the onRemove handler in useDraggable.ts:

const onRemove = (evt: SortableEvent) => {
  const { from, item, oldIndex, oldDraggableIndex, pullMode, clone } = evt
  insertNodeAt(from, item, oldIndex)  // <-- Problem: Re-inserts before checking pullMode
  if (pullMode === 'clone') {
    removeNode(clone!)
    return
  }
  // ... data update logic
}

The fix should be:

const onRemove = (evt: SortableEvent) => {
  const { from, item, oldIndex, oldDraggableIndex, pullMode, clone } = evt
  
  if (pullMode === 'clone') {
    removeNode(clone!)
    return
  }
  
  // Only re-insert if not a clone operation
  insertNodeAt(from, item, oldIndex)
  
  // ... data update logic
}

This would:
Check pullMode first
Only re-insert the item if it's not a clone operation
3. Prevent the duplicate DOM element issue

@TheKucel
Copy link

+1 here

@kpschaper
Copy link

+1 here
@Alfred-Skyblue should I make a PR?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants