Angular 7 Uploads Backed by Node.js

Angular 7 Uploads Backed by Node.js

<strong>In this tutorial, you'll learn how to create an app with a backend built on Node.js and Express, and a front-end created with Angular 7.</strong>

In this tutorial, you'll learn how to create an app with a backend built on Node.js and Express, and a front-end created with Angular 7.

Web development has become more dynamic with time, mostly due to the continued development of various languages, tools, and frameworks, one of them being Angular. The recent release of Angular 7 comes with new features, such as virtual scrolling, drag and drop, and some CLI updates, among others.

In this article, we will be building an application that shows how file upload works (specifically, image upload). It also uses the Angular Material and its CDK module to show the drag and drop feature introduced with Angular v7.

Below is a screenshot of what we will be building:

Getting Started: Configuring the Development Environment

  • For this tutorial, you can download and install the Angular IDE.
  • However, if you already have an Eclipse installation you are happy with, you can add Angular IDE to it from the Eclipse marketplace.
  • If you already have CodeMix installed, simply ensure you have the Angular extension Pack installed from the Extension Manager at Help > CodeMix Extensions.

Creating an Angular Project Using Angular IDE

We will create our application using the Angular IDE project wizard. We will be using Angular CLI version 7.3.6 and the latest version of all the tech libraries and stacks, as at the time of this writing. To create a new Angular project, navigate to File>New>Angular Project.

The next step is to add the Angular Material module that also adds the CDK module (which contains the drag and drop feature in Angular v7). Note that this also optionally adds the animation module. We will include the Angular Material module by running the command below in Terminal+:

ng add @angular/material

At this stage, we will move on to pulling in some dependencies that we will use to build the application with the command below:

npm install --save express cors multer mkdirp 
  • Express is a Node.js module that simplifies the creation of a node server.
  • Cors is a Node.js module that provides a middleware to handle cross-origin resource sharing.
  • Multer is a Node.js middleware for handling “multipart/form-data,” which is primarily used for uploading files.
  • Mkdirp is a Node.js module for directory creation.

Setting Up the Backend Server

Now, we can begin the development of the application. First, we will create a server.js file in the root directory of our application. This file will contain the server setup, multer configuration, and the only route of the application. The route will accept the files submitted, save them, and return a path to the files.

const express = require('express');
const multer = require('multer');
const cors = require('cors');
const mkdirp = require('mkdirp');
const app = express();
const PORT = 5000;
const URL = `http://localhost:${PORT}/`;
var storage = multer.diskStorage({
    destination: (req, file, cb) => {
        const dir = './public/images/uploads';
        mkdirp(dir, err => cb(err, dir))
    filename: (req, file, cb) => {
        cb(null, + '-' + file.originalname)
const upload = multer({ storage })
app.use(cors());'/upload', upload.single('image'), (req, res) => {
    if (req.file) {
        res.json({imageUrl: `${URL}images/uploads/${req.file.filename}`});
        res.status("409").json("No Files to Upload.");
console.log('api runnging on port: ' + PORT);

In the code snippet above, we set up Express to load files in the public directory in the root of the project as static or public files. This allows the files to be rendered through requests to the file path from the root URL. For example, for a file image.jpg in the public directory, a request to http://localhost:5000/image.jpg from the browser will render the image.

Next, we set up the configuration for the multer middleware, which determines how and where the files are to be saved. In this case, we store the files in the public/images/uploads directory. In this setup, we made use of the mkdirp module to create the uploads directory, if it doesn’t exist.

Afterwards, we created the route to which the images will be posted. On the route definition, the multer middleware (object) is passed as a parameter. This helps the route to accept single file upload, with the expected file in the field name image. We then return the file’s path as part of the response, or return an error if no file is found.

We can run the application back end using the command given below:

node server.js

Setting Up the Front-End

Now that we have the application’s backend running, let’s begin the development of its front-end. For brevity’s sake, we will be building the entire application in just one component (i.e. the app component).

First, we need to register the drag and drop module from the @angular/cdk module in the app.module.ts file, as shown below:

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { HttpClientModule } from "@angular/common/http";
import { AppComponent } from './app.component';
import { DragDropModule } from "@angular/cdk/drag-drop" //<--- imported here
  declarations: [
  imports: [
    DragDropModule // <--- registered here
  providers: [],
  bootstrap: [AppComponent]
export class AppModule { }

Next up, we set up the app.component.ts file. This is where most of our application logic resides.

Here, we will set up the upload event handler, the image upload handler, as well as the drop event handler of the CDK drag and drop lists.

import { Component } from '@angular/core';
import { HttpClient } from "@angular/common/http";
import { HttpEventType } from "@angular/common/http";
import {moveItemInArray, transferArrayItem, CdkDragDrop} from "@angular/cdk/drag-drop"

// Image model which also holds the upload progress and the file class ImageFile { file: File; uploadProgress: string; } @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent {

images: ImageFile[] = []; //an array of valid images imageUrls: string[] = []; //an array of uploaded image urls favourites: string[] = []; //an array of favorite image urls message: string = null; //a string to report the number of valid images

constructor(private http : HttpClient) { } //depedency injection

selectFiles = (event) => { //image upload handler this.images = []; let files : FileList =; for (let i = 0; i < files.length; i++) { if (files.item(i).name.match(/.(jpg|jpeg|png|gif)$/)) { //image validity check this.images.push({file: files.item(i), uploadProgress: "0"}); } } this.message = ${this.images.length} valid image(s) selected; } uploadImages(){ //image upload hander, index) => { const formData = new FormData(); formData.append("image", image.file,; return'http://localhost:5000/upload', formData, { reportProgress: true, observe: "events" }) .subscribe(event => { if (event.type === HttpEventType.UploadProgress ) { image.uploadProgress = ${(event.loaded / * 100)}%; } if (event.type === HttpEventType.Response) { this.imageUrls.push(event.body.imageUrl); } }); }); } drop(event: CdkDragDrop<string[]>) { //cdkdrop event handler if (event.previousContainer !== event.container) { // this handles moving an item between to list. // here we can attach a server request to persist the changes transferArrayItem(, // the list from which the item is picked, // the list to which the item is to be placed event.previousIndex, event.currentIndex ); } else { // this handle when a list is being rearranged moveItemInArray(, // list to be rearranged event.previousIndex, event.currentIndex ); } } }

At the top of this file, we imported the modules needed for this component, which include the HttpClient and the HttpEventType. In Angular, the former is used to handle the request, much like the request handling using Axios. HttpEventType is used to check the response event type (uploadProgess event is when the request data is still being uploaded, while the response event is when the response data is sent to the client). We also imported three things from the CDK module. The first one is the moveItemArray method which is used to move items from one position to another (i.e. it rearranges the list). The second one is the transferArrayItem method which is used to transfer an item from one list to another. Finally, we imported the CdkDragDrop which is used to hint the type of event the drop event handler expects.

Next, we declared a model to describe the file struct which includes the file upload progress as a percentage (usually this class would be in a separate file and folder as a model).

Next, we defined three methods that handle specific events in the component, and they are as follows:

  • The selectFiles method is used to handle the change event of the input field. It accepts the event that has a FileList.
  • Note: Although FileList has a length property, it is not an array; hence, it does not have high order methods, such as map, filter, etc.
  • The selectFiles method filters the list and returns only valid images for upload.
  • The uploadImages method sends the images to the server one after the other, using the FormData object provided by JavaScript. In the subscribe method (more like the then method of JavaScript promises) we accept the response event and act accordingly. For example, if the event is an upload progress event, we get the percentage of completion and return it to be rendered to the user. When the request has been completed, we push the returned image URL to the array of uploaded image URLs.
  • The drop method is used to respond to the drag and drop event. This method handles an item moving up and down a particular list, or between two connected lists. In this method, we can attach server calls (to save the changes) when we move an item from the regular list to the favorites list (although in this application, changes are not persisted).

Next, we edit the app.component.html file. Here, we render the list of images and the input for the image upload. The file is edited as shown below:

  <!-- form -->
  <div class="col-sm-12">
    <h1>Image Uploader</h1><hr/>
    <button class="btn btn-primary" (click)="">Select Images</button>
    <input class="form-control d-none" type="file" (change)="selectFiles($event)" multiple #imageInput/>
    <button class="btn btn-success float-right" (click)="uploadImages()">Upload</button>
    <p class="text-info" *ngIf="message"><strong>{{message}}</strong></p>

&lt;!-- upload progress --&gt;
&lt;div class="col-12" *ngFor="let image of images"&gt;
  &lt;div class="progress" style="margin-bottom: 10px" *ngIf="image.uploadProgress"&gt;
    &lt;div class="progress-bar progress-bar-striped progress-bar" role="progressbar" aria-valuenow="75" aria-valuemin="0" naria-valuemax="100" [ngStyle]="{'width': image.uploadProgress }"&gt;&lt;/div&gt;


<!-- drag and drop list--> <hr/> <div class="row"> <div cdkDropList [cdkDropListData]="imageUrls" [cdkDropListConnectedTo]="secondList" #firstList="cdkDropList" (cdkDropListDropped)="drop($event)" class="col-2 offset-2 card" style="min-height: 100px"> <h4>Images</h4> <div ngFor="let imageUrl of imageUrls" class="pop" cdkDrag> <img src="{{imageUrl}}" class="img-thumbnail" alt="not available"/><br/> </div> </div> <div cdkDropList [cdkDropListData]="favourites" [cdkDropListConnectedTo]="firstList" #secondList="cdkDropList" (cdkDropListDropped)="drop($event)" class="col-2 offset-2 card" style="min-height: 100px"> <h4>Favourites Images</h4> <div *ngFor="let imageUrl of favourites" class="pop" cdkDrag> <img src="{{imageUrl}}" class="img-thumbnail" alt="not available"/><br/> </div> </div> </div> </div>

Here the file input is hidden from the user and given an #imageInput handle which is used by the button shown to the user to trigger the click event of the file input. Also, the selectFiles method previously defined is attached to the on change event of the file input.

Next, the upload progress of the files is displayed. This is achieved using the upload progress attached to each ImageFile object in the images array.

Finally, we render the uploaded images using their URLs in the imageUrls and favorites array. For the first array, we attach the cdkDropList attribute to indicate that this is a list with the drag and drop functionalities handled by the CDK module. We then pass the array of image URLs to the cdkDropListData property for the CDK module to handle the changes using this array as its data target. We then connect it to the other list (in this case, the favorites list) using the cdkDropListConnectedTo property. Next, we attach the drop event handler using the cdkDropListDropped Angular created custom event. Finally, on each item, we attach the cdkDrag to make them draggable and droppable. We do the same for the favorites list and name it the #secondList. Now we should be able to drag items between lists, as well as up and down the same list.

Run the Application

Run the application from the server tab of the Angular IDE.

Now we are done with the development of this application. Congratulations!


In this article, we created a Node.js backend using Express, which accepts file input, saves it, and returns the file path for rendering. We built a front-end with the Angular framework, taking advantage of the Angular CDK’s drag and drop module.

As always, this is a simple application that can be improved by using data persistence, and breaking up the application into smaller, more manageable components. Moving the application’s data handling into a service would be a good step too.

Originally published by George Anderson at

Follow great articles on Twitter

Learn More

☞ Angular 7 (formerly Angular 2) - The Complete Guide

☞ Learn and Understand AngularJS

☞ Angular Crash Course for Busy Developers

☞ The Complete Angular Course: Beginner to Advanced

☞ Angular (Angular 2+) & NodeJS - The MEAN Stack Guide

☞ Become a JavaScript developer - Learn (React, Node,Angular)

☞ Angular (Full App) with Angular Material, Angularfire & NgRx

angular node-js

Bootstrap 5 Complete Course with Examples

Bootstrap 5 Tutorial - Bootstrap 5 Crash Course for Beginners

Nest.JS Tutorial for Beginners

Hello Vue 3: A First Look at Vue 3 and the Composition API

Building a simple Applications with Vue 3

Deno Crash Course: Explore Deno and Create a full REST API with Deno

How to Build a Real-time Chat App with Deno and WebSockets

Convert HTML to Markdown Online

HTML entity encoder decoder Online

How to Hire Node.js Developers And How Much Does It Cost?

A Guide to Hire Node.js Developers who can help you create fast and efficient web applications. Also, know how much does it cost to hire Node.js Developers.

Angular 8 Node & Express JS File Upload

In this Angular 8 and Node.js tutorial, we are going to look at how to upload files on the Node server. To create Angular image upload component, we will be using Angular 8 front-end framework along with ng2-file-upload NPM package; It’s an easy to use Angular directives for uploading the files.

Hire Node.JS Developers | Skenix Infotech

We are providing robust Node.JS Development Services with expert Node.js Developers. Get affordable Node.JS Web Development services from Skenix Infotech.

How to Implement Server Side Pagination with Angular 8 and Node.js

A simple example of how to implement server-side pagination in Angular 8 with a Node.js backend API.

Hands on with Node.Js Streams | Examples & Approach

The practical implications of having Streams in Node.js are vast. Nodejs Streams are a great way to handle data chunks and uncomplicate development.