Vue.Draggable
Vue.Draggable copied to clipboard
How to cancel drop when hitting escape
Hi there,
I have two different lists with the same group to interchange items between them.
Hitting escape in the middle of a drag operation cancels the drag operation and lets the item on its original list only if the dragged element wasn't already over the destination list. If the dragged element is already over the destination, hitting escape acts as if I dropped the item (triggers unchoose
, add
and so on)
I need to be able to hit escape at any moment and cancel the whole operation, leaving the item on its original list.
I did read the :move
prop but it doesn't seem to help on this. (by the way, the two links are broken on: "See complete example: Cancel.html, cancel.js")
Thanks for your help
I came here for this reason as well. Not only does escape persist the current move position, but also dragging to an invalid location outside the list (you can a stop cursor) and releasing the drag-drop persists at the last move position. In both cases I want the change to be reverted. Both of these standard user-scenarios seem like user cancellation of the operation...
Is there a solution for this?
The same question. How make cancel if user dragging to an invalid location outside the list.
Partial solution
Theoretically, we should be able to check whether the drop was canceled or not, using the native drag-and-drop API:
- https://developer.mozilla.org/en-US/docs/Web/API/HTML_Drag_and_Drop_API/Drag_operations
- https://developer.mozilla.org/en-US/docs/Web/API/DataTransfer/dropEffect but it seems that the property isn’t set and we have the following:
onDragEnd(event) {
if (event.originalEvent.dataTransfer.dropEffect == "none")
// this is always true as if the event was always canceled...
:-(
However, a couple other properties can be seen as candidates for discriminating between the “drop“ and the “cancel“ operations:
// - event.originalEvent.type ...............: "drop" vs. "dragend"
// - event.originalEvent.returnValue ........: false = drop, true = cancel
// - event.originalEvent.defaultPrevented ...: true = drop, false = cancel
:-)
Remaining problems
This works for the "Escape" key press, but I haven't tried it with a drop outside of the drop area...
Also another problem remains: in another implementation of draggable
, it doesn't listen to the Escape
key at all. I don't know how to make it do so and reuse the solution I have found. (Alternatively, I can listen for the Escape key being pressed, but I don't know how to make it trigger the process that leads to onDragEnd
.)
I found a hacky workaround for this problem with wasting 2 hours 😷. I've checked the code and it seems to be a bug.
// On template: <draggable ref="draggableComponentRefName">
// On mounted() or somewhere: set sortable.js option directly
setTimeout(() => {
this.$refs.draggableComponentRefName._sortable.option('onMove', (evt, originalEvent) => {
console.log({evt, originalEvent})
debugger
return false
})
}, 500)
I ended up checking dataTransfer.items which is an empty array if the drag is canceled with escape key.
onAdd(event) {
//if the drag was canceled with ESC
if (event.originalEvent.dataTransfer.items.length === 0) {
return
}
}