-
-
Save chinhvo/ce785dc41816acf841e95ae7f0f5147c to your computer and use it in GitHub Desktop.
Angular Drag and Drop File Directive
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { Directive, EventEmitter, HostBinding, HostListener, Input, Output } from '@angular/core'; | |
// Angular Drag and Drop File | |
// | |
// Add this directive to an element to turn it into a dropzone | |
// for drag and drop of files. | |
// Example: | |
// | |
// <div (appDropZone)="onDrop($event)"></div> | |
// | |
// Any files dropped onto the region are then | |
// returned as a Javascript array of file objects. | |
// Which in TypeScript is `Array<File>` | |
// | |
@Directive({ | |
selector: '[appDropZone]' | |
}) | |
export class DropZoneDirective { | |
// The directive emits a `fileDrop` event | |
// with the list of files dropped on the element | |
// as an JS array of `File` objects. | |
@Output('appDropZone') fileDrop = new EventEmitter<Array<File>>(); | |
// Disable dropping on the body of the document. | |
// This prevents the browser from loading the dropped files | |
// using it's default behaviour if the user misses the drop zone. | |
// Set this input to false if you want the browser default behaviour. | |
@Input() preventBodyDrop = true; | |
// The `drop-zone-active` class is applied to the host | |
// element when a drag is currently over the target. | |
@HostBinding('class.drop-zone-active') | |
active = false; | |
@HostListener('drop', ['$event']) | |
onDrop(event: DragEvent) { | |
event.preventDefault(); | |
this.active = false; | |
const { dataTransfer } = event; | |
if (dataTransfer.items) { | |
const files = []; | |
for (let i = 0; i < dataTransfer.items.length; i++) { | |
// If dropped items aren't files, reject them | |
if (dataTransfer.items[i].kind === 'file') { | |
files.push(dataTransfer.items[i].getAsFile()); | |
} | |
} | |
dataTransfer.items.clear(); | |
this.fileDrop.emit(files); | |
} else { | |
const files = dataTransfer.files; | |
dataTransfer.clearData(); | |
this.fileDrop.emit(Array.from(files)); | |
} | |
} | |
@HostListener('dragover', ['$event']) | |
onDragOver(event: DragEvent) { | |
event.stopPropagation(); | |
event.preventDefault(); | |
this.active = true; | |
} | |
@HostListener('dragleave', ['$event']) | |
onDragLeave(event: DragEvent) { | |
this.active = false; | |
} | |
@HostListener('body:dragover', ['$event']) | |
onBodyDragOver(event: DragEvent) { | |
if (this.preventBodyDrop) { | |
event.preventDefault(); | |
event.stopPropagation(); | |
} | |
} | |
@HostListener('body:drop', ['$event']) | |
onBodyDrop(event: DragEvent) { | |
if (this.preventBodyDrop) { | |
event.preventDefault(); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment