JavaScriptJavaScript

Drag'n'Drop Event Handling Gotchas I Wish I Knew Earlier

Aug 16, 2018 · Updated: Jul 12, 2021 · by Tim Kamanin

I'll explain the gotchas in a plain HTML/JS pseudocode, but these concepts apply to every way you might write your JS code: react, vue, svelte, vanilla, whatever.

Gotcha #1: If you want a div to accept drop event and listen to drag events i.e. become "droppable" there are two conditions that need to be fulfilled:

  1. The element should provide a handler for ondragover event:

    <div id="droparea" ondragover="handleDragOver();"></div>
    

  2. The element should provide a handler for ondop event

    <div id="droparea" ondrop="handleDrop();"></div>
    

As a result it should look like:

<div id="droparea" ondragover="handleDragOver();" ondrop="handleDrop();"></div>

And now you need to know the second gotcha:

Gotcha #2: In order to have the drop event happen on a div element, you must cancel "ondragenter" and "ondragover" events.

So what we've done above is not enough. We need to stop propagation and prevent default behaviors for ondragenter and ondragover events.

As a result, your pseudocode should look like this:

<div
  id="droparea"
  ondragenter="event.stopPropagation(); event.preventDefault(); handleDragEnter(event);"
  ondragover="event.stopPropagation(); event.preventDefault(); handleDragOver(event);"
  ondrop="event.stopPropagation(); event.preventDefault(); handleDrop(event);"
></div>

Gotcha #3: Google Chrome console has a bug and shows event.dataTransfer.files as empty but it's not!

When you process dropped files in the onDrop handler and want to console.log event and check if it contains any files you won't see a file list in the output:

function onDropHandler(event) {
  event.preventDefault();
  console.log(event);
}

// Shows event.dataTransfer.files and event.dataTransfer.items as empty

That's a little async-related gotcha. To solve this, instead, console.log event.dataTransfer.files directly:

function onDropHandler(event) {
  event.preventDefault();
  console.log(event.dataTransfer.files);
}

// Now should be good!

Enjoy dragging and dropping!

Hey, if you've found this useful, please share the post to help other folks find it:

There's even more:

Subscribe for updates

  • via Twitter: @timonweb
  • old school RSS:
  • or evergreen email ↓ ↓ ↓