Angular 8 drag drop dragover dragleave events not firing

Viewed 5064

I'm trying to implement a drag and drop file upload in angular 8, heavily inspired by this article, and this one.

I cant get any of the drag events to fire. I've checked that the DragDropDirective is imported by using mouseenter methods in the same directive, which launch correctly, i also see that style that i added is correctly applied.

I've been banging my head against this all day, what am i missing?

Edit: This works with files from a Files explorer, but not with files from the desktop. Using Ubuntu 19.

// component.html
<section appDragDrop class="panel" id="dropzone-wrapper" (onFileDropped)="uploadFile($event)">
    <input type="file" #fileInput (change)="uploadFile($event.target.files)" accept=".json" hidden>
    <label for="dropzone">
        <span>
            drag and drop here.
        </span>
    </label>
</section>

import { Directive, Output, Input, EventEmitter, HostBinding, HostListener, ElementRef } from '@angular/core';

@Directive({
  selector: '[appDragDrop]'
})
export class DragDropDirective {
  el: ElementRef
  constructor(el: ElementRef) {
    el.nativeElement.style.backgroundColor = 'yellow';
  }

  // Working fine
  @HostListener('mouseenter') onMouseEnter() {
    console.log('mouse entering')
  }
  
  // Working fine
  @HostListener('mouseleave') onMouseLeave() {
    console.log('mouse leaving')
  }

  // --- Not working ---
  @HostListener('dragover', ['$event']) onDragOver(evt) {
    console.log('A')
  }

  // --- Not working ---
  @HostListener('dragleave', ['$event']) public onDragLeave(evt) {
    console.log('B')
  }

  // --- Not working ---
  @HostListener('drop', ['$event']) public ondrop(evt) {
    console.log('C')
  }
}

NOTE

Drag and drop doesn't seem to work from screen to screen on linux, you need to test with files from the same screen.

3 Answers

If you want to use Drag and Drop event for file upload you should use window:dragenter event listener. This event starts file drag into window and when drag event started then dragover, dragleave and drop will work as well.
Example:

// missing listener which detects that something was dragged into window area
@HostListener('window:dragenter', ['$event'])
onWindowDragEnter(event: any): void {
  event.preventDefault();
  event.stopPropagation();
}

@HostListener('dragover', ['$event'])
onDragOver(event: any): void {
  event.preventDefault();
  event.stopPropagation();
  // ...
}

@HostListener('dragleave', ['$event'])
public onDragLeave(event: any): void {
  event.preventDefault();
  event.stopPropagation();
  // ...
}

@HostListener('drop', ['$event'])
public onDrop(event: any): void {
  event.preventDefault();
  event.stopPropagation();
  // ...
}

However solution wasn't tested on Ubuntu

Better late than never, but it works for me:

@HostListener("dragover", ["$event"]) onDragOver(event: any) {
  event.preventDefault()
}
@HostListener('drop', ['$event']) onDrop(event: any): boolean {
  console.log("drop", event)
  return false
}
Related