You have unlimited access as a PRO member
You are receiving a free preview of 3 lessons
Your free preview as expired - please upgrade to PRO
Contents
Recent Posts
- Object Oriented Programming With TypeScript
- Angular Elements Advanced Techniques
- TypeScript - the Basics
- The Real State of JavaScript 2018
- Cloud Scheduler for Firebase Functions
- Testing Firestore Security Rules With the Emulator
- How to Use Git and Github
- Infinite Virtual Scroll With the Angular CDK
- Build a Group Chat With Firestore
- Async Await Pro Tips
Drag and Drop File Uploads to Firebase Storage
Episode 14 written by Jeff Delaney
Good news! Firebase Storage is now supported natively in AngularFire2. Checkout the AngularFire Storage Dropzone lesson for the latest and greatest information.
In this lesson, I am expanding on the my previous file upload lesson with a drag and drop directive from scratch. There are several JS libraries, such as dropzone, that provide this functionality, but it’s not always easy to implement with backend storage. So let’s just do it with pure Angular/TypeScript code. The goal is to allow users to drop files into a div in Angular that will automatically trigger the upload process to Firebase storage.
ng g service upload |
Building the Service
First, we need a basic Upload class that defines the specific attributes we want to set before pushing the file to the storage and/or the database.
upload.ts
export class Upload { |
I’m not going to go into detail here because this is covered in a separate file upload lesson, check it out for more detail on the upload service code. Basically, we import the Firebase SDK, make a reference to the storage location, then interact with the promise as it uploads the files. Here is the minimum code necessary in the service to use the drag and drop feature.
upload.service.ts
import { Injectable } from '@angular/core'; |
File Drop Attribute Directive
We are going to use an Angular attribute directive for file uploads, instead of a component. The drag and drop field does not need a template, so it’s a perfect situation for a custom directive.
The purpose of the drop files directive is to receive the raw files as a JavaScript FileList, then emit them to the parent component. It will also emit a custom event when files are hovered on the the drop zone area. Here’s how it works step-by-step.
1 First we create the custom events using the @Output
decorator and EventEmitter
. The filesDropped
event will emit the FileList, and the filesHovered event will emit a boolean.
2 The HostListener event can hook into standard JavaScript browser events. When files are dropped into element, we can get the transferred data and emit it to the parent component. It also necessary to call preventDefault() because the browser will navigate to the local file path when the files are dropped.
3 The directive also listens to the dragover
and dragleave
events to toggle and emit the custom filesHovered
event. In the component, we will use this state to change the CSS class when the user is hovering over the drop zone with files.
file-drop.directive.ts
import { Directive, EventEmitter, HostListener, Output } from '@angular/core'; |
Upload Form Component
The upload-form component is responsible for receiving the files, converting them to the Upload
class, then triggering upload service. The component listens for the filesDropped event, and when it occurs it loops through the FileList with Lodash, and pushes each file to firebase storage.
It also listens to the filesHovered event and toggles the dropzoneActive variable. In the template, this variable is used with ngClass to show the user when the files are hovered.
upload-form.component.ts
import { Component } from '@angular/core'; |
In the template, the attribute directive will emit the events automatically, so we just need to tell the component which function to run when they happen.
<div *ngIf="currentUpload"> |
Ideas for Improvement
The current directive works, but there are ways it can be improved. First, the files are not being validated, so it’s possible for the user to upload files of any size or format. It would be a good idea to throw an error if the file exceeds a maximum size or doesn’t match a certain format. Second, it would be useful to add a button that cancels the Firebase upload process if it hangs from a poor internet connection.
That’s it for drag and drop file uploads with Angular. Good luck!