SortableJS / Sortable

Reorderable drag-and-drop lists for modern browsers and touch devices. No jQuery or framework required.
https://sortablejs.github.io/Sortable/
MIT License
29.68k stars 3.7k forks source link

[bug] Cancel drag from the outside / Cannot read properties of null (reading 'Sortable..') in _emulateDragOver #2307

Open Kasheftin opened 1 year ago

Kasheftin commented 1 year ago

Repro & Source Code Here's the repro: https://kasheftin.github.io/vuedraggable-bug/ Here's the source code: https://github.com/Kasheftin/vuedraggable-bug

Versions sortablejs = ^1.15.0 @types/sortablejs = ^1.15.1 vuedraggable = ^4.1.0

Repro steps

  1. Go to https://kasheftin.github.io/vuedraggable-bug/.
  2. Click on the "blink" button. This button adds a temporary item to the list. The item is removed after 5 seconds.
  3. Start dragging the created item to the other column but don't mouse up, just hold it.
  4. Wait 5 seconds until the source element is removed.
  5. Console starts spamming messages like Uncaught TypeError: Cannot read properties of null (reading 'Sortable1692890267221')
  6. Mouse Up.
  7. Fake (non-existent) item is being readded to the list. There's a store vs. DOM tree resynchronization (not sure about this step, it might be vuedraggable@next bug).

Demo Peek 2023-08-24 18-33

Motivation / Real-world example We are developing a real-time application. Imagine some kind of kanban board that is used by multiple users at the same time. One user can start dragging a card while another user might delete it. In this case, we get several errors related both to sortable.js and vuedraggable. Sortable.js bug is definitely the repro step №5. We use forceFallback option, and the bug happens in _emulateDragOver function while trying to evaluate dragEl.parentNode[expando]._isOutsideThisEl(target). It looks like dragEl is detached from the DOM, and it has parentNode=null.

However, our main goal here is to be able to cancel the drag. If some item is being dragged while another user deletes it, we want the drag to stop. I tried to set disabled prop to true temporary, but it does not work, a ghost item still follows the cursor. Obviously, it's not related to any checks in move and other events, because it's something that happens from the outside. The socket receives the message about item deletion, the item is removed from the store, it matches the currently dragged item.id, hence we have to trigger some cancel method in sortable.js which removes the ghost item and stops the drag logic.

pedroAlba commented 10 months ago

⬆️

Facing similar issues, can't figure out a way to cancel the drag-n-drop operation when the item has modified externally i.e websockets.

A cancel operation would work, when a new websocket message is received, all "current" drag and drop operations could be cancelled.

shekharpandey93 commented 10 months ago
Screenshot 2023-12-22 at 8 28 09 PM

Facing similar issues, can't figure out a way to cancel the drag-n-drop operation, due to all system hang up