Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get files from angular 2 onDrop event?

I tried like this but onDrop method don't return image files when I drop to it...

onDragStart(event, data: any) {
  event.dataTransfer.setData('data', data);
}
onDrop(event, data: any) {
  let dataTransfer = event.dataTransfer.getData('data');
  event.preventDefault();
}
allowDrop(event) {
  event.preventDefault();
}
<div (drop)="onDrop($event, dropData)" (dragover)="allowDrop($event)"></div>
<div (dragstart)="onDragStart($event, dragData)"></div>

Any solution for this?

like image 473
Vladimir Avatar asked Mar 23 '17 21:03

Vladimir


4 Answers

The event onDrop event fires only when onDragOver has preventDefault() and stopPropagation() methods run on event.

HTML

<div
    (drop)="onDrop($event)"
    (dragover)="onDragOver($event)"
>
    Drop target
</div>

DropComponent.ts

export class DropComponent {
    onDrop(event) {
        event.preventDefault();
    }
    onDragOver(event) {
        event.stopPropagation();
        event.preventDefault();
    }
}

UPDATE

This is required because by default the browser prevents anything from happening while dropping onto the HTML element. See more at MDN - Defining a valid drop zone

like image 157
maryl Avatar answered Oct 13 '22 10:10

maryl


Here is the complete code for drag and drop in Angular 2/4/6 :

drag.component.ts:

import { Component } from '@angular/core';

@Component({
  selector: 'drag-root',
  templateUrl: './drag.component.html',
  styleUrls: ['./drag.component.css']
})
export class AppComponent {

  allowDrop(ev) {
    ev.preventDefault();
  }

  drag(ev) {
    ev.dataTransfer.setData("text", ev.target.id);
  }

  drop(ev) {
    ev.preventDefault();
    var data = ev.dataTransfer.getData("text");
    ev.target.appendChild(document.getElementById(data));
  }
}

drag.component.html:

<h2>Drag and Drop</h2>
<div  id="div1" 
      (drop)="drop($event)" 
      (dragover)="allowDrop($event)">

      <img 
      src="https://images.pexels.com/photos/658687/pexels-photo-658687.jpeg?auto=compress&cs=tinysrgb&h=350" 
      draggable="true" 
      (dragstart)="drag($event)" 
      id="drag1"
      width="88" 
      height="31">
</div>

<div id="div2" 
  (drop)="drop($event)" 
  (dragover)="allowDrop($event)">
</div>

drag.component.css:

#div1, #div2 {
    float: left;
    width: 100px;
    height: 35px;
    margin: 10px;
    padding: 10px;
    border: 1px solid black;
}

Snapshots:

Drag 1

Drag 2

like image 30
Shubham Verma Avatar answered Oct 13 '22 08:10

Shubham Verma


You could wrap the onDrop functionality into a reusable directive. Like this:

https://gist.github.com/darrenmothersele/7afda13d858a156ce571510dd78b7624

Apply this directive to an element:

<div (appDropZone)="onDrop($event)"></div>

The event is fired with a JavaScript array of the dropped Files. So, your onDrop implementation in the component looks something like this:

onDrop(files: FileList) {
  console.log({ files });
}
like image 6
Darren Avatar answered Oct 13 '22 08:10

Darren


As the others stated you need to call event.preventDefault() and event.stopPropagation() on the (dragover) event to make your container a valid dropzone.

I've written a highly customizable Angular component which implements the correct Drag'n'Drop behavior so I don't need to copy it over and over again which returns a list of the dropped files as an output event.
This can be found here.

After you imported the module you have access to the component:

<ngx-dropzone [multiple]="false" [maxFileSize]="2000"></ngx-dropzone>

You have some options to set and it comes with a decent default styling (screenshots can be found in the GitHub repo). If you want to, you can even take your own div container with your custom styles and hover effects and put it in the dropzone. Details on this can be found in the API description.

<ngx-dropzone [customContent]="customDropzone" (filesAdded)="onFilesDropped($event)">
<ng-template #customDropzone>
    <div class="custom-dropzone">
        This is my custom content
    </div>
</ng-template>

like image 1
Peter Freeman Avatar answered Oct 13 '22 10:10

Peter Freeman