How Do You Make a Drag-And-Drop File Uploader In Angular

Hello everyone, In this tutorial, we will make a simple Angular app that we’ll utilize to make a custom directive for Angular drag and drop functionalities.

Introduction:

First of all we need to angular cli to create angular project. Once it is installed open the terminal & type the following command.

ng new drag-drop

Above command generate new project.

In the app.component.html file, we will write the following HTML structure to define our drop zone:

<div *ngIf="!files.length" class="col-12 rmpm dropzone" appDragDrop (files)="filesDropped($event)">
  <div class="text-wrapper">
    <div class="centered">Drop your file here!</div>
  </div>
</div>
<!--droped image preview-->
<div *ngFor="let file of files">
  <img *ngIf="file" [src]="file.url" width="100px" height="100px">
</div>

<button type="button" (click)="upload()">Upload Image</button>

now we need to create directives, to create a directive, we must be in the folder where we intend to put it and execute the following angular-cli command:

ng generate directive drag-drop

After that, we should discuss about directives. On angular, there are three types of directives.

Components are the most commonly used (and we’ve already used one). Each part of our application’s behaviour is defined by this type of directive.

The second kind is structural directives, which modify the dom of the application in response to certain circumstances or expressions expressed on them.

The third kind is attribute directives, which affect the style, classes, and properties of the element to which they are connected.

Angular-cli will produce two files in our current directory as a result of above command:

drag-drop.directives.ts

drag-drop.directives.spec.ts

After that, add HostListener to detect Drag Over, Drag Leave, and finally Dropping the file.

drag-drop.directives.ts 

import {
  Directive,
  HostBinding,
  HostListener,
  Output,
  EventEmitter
} from "@angular/core";
import { DomSanitizer, SafeUrl } from '@angular/platform-browser';

export interface FileHandle {
  file: File,
  url: SafeUrl
}

@Directive({
  selector: "[appDragDrop]"
})
export class DragDirective {
  @Output() files: EventEmitter<FileHandle[]> = new EventEmitter();

  @HostBinding("style.background") private background = "#eee";

  constructor(private sanitizer: DomSanitizer) { }

  @HostListener("dragover", ["$event"]) public onDragOver(evt: DragEvent) {
    evt.preventDefault();
    evt.stopPropagation();
    this.background = "#999";
  }

  @HostListener("dragleave", ["$event"]) public onDragLeave(evt: DragEvent) {
    evt.preventDefault();
    evt.stopPropagation();
    this.background = "#eee";
  }

  @HostListener('drop', ['$event']) public onDrop(evt: DragEvent) {
    evt.preventDefault();
    evt.stopPropagation();
    this.background = '#eee';
  
    let files: FileHandle[] = [];
    for (let i = 0; i < evt.dataTransfer.files.length; i++) {
      const file = evt.dataTransfer.files[i];
      const url = this.sanitizer.bypassSecurityTrustUrl(window.URL.createObjectURL(file));
      files.push({ file, url });
    }
    if (files.length > 0) {
      this.files.emit(files);
    }
  }
}

app.component.css

p {
  font-family: Lato;
}
.dropzone {
  min-height: 300px;
  width: 400px;
  padding:2rem;
  border:dashed 4px #979797;
  display: table;
}

.text-wrapper {
  position: absolute;
  text-align: center;
  transform: translate(50%, 50%);
}

.centered {
  font-family: sans-serif;
  font-size: 1.3em;
  font-weight: bold;
  text-align:center;
}

app.component.ts

import { Component } from '@angular/core';
import { FileHandle } from './dragDrop.directive';

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.css' ]
})
export class AppComponent  {
 
  files: FileHandle[] = [];

  filesDropped(files: FileHandle[]): void {
    this.files = files;
  }

  upload(): void {
    //get image for upload;
  }
}

Now you can run it.

OUTPUT:

Submit a Comment

Your email address will not be published. Required fields are marked *

Subscribe

Select Categories