Angular 9/8 How-To: Build a Material File Upload UI with MatProgressBar, MatButton , MatIcon and MatCard

  • Author: Ahmed Bouchefra

In this quick how-to tutorial, we'll see how to build a file/image uploading UI with Angular 9 Material components such as MatProgressBar, MatIcon, MatCard, and MatButton.

If you are new to these how-tos, check out how to install and set up a project and the prerequisites.

Angular 9 Material Progressbar

ProgressBar is a material component for displaying progress and activity. In our Angular 9 example, we'll use it to indicate the activity for uploading images with HttpClient.

We'll only build the UI in this article, for building the service for actually uploading files, check out this how-to tutorial instead.

Step 1 — Generating an Angular 9 Component

In the first step, run the following command to generate a component named home:

$ ng generate component home

Step 2 — Importing Angular 9 Material Components

In the second step, we need to import the modules of the required Angular Material components i.e MatProgressBar, MatIcon, MatCard, and MatButton.

Go to the src/app/app.module.ts file and add the following imports:

import {   
  MatIconModule,  
  MatCardModule,  
  MatButtonModule,  
  MatProgressBarModule } from '@angular/material';

Next, you need to add the imported modules to the imports array as follows:

@NgModule({  
  declarations: [  
    AppComponent,  
    HomeComponent,  
    AboutComponent  
  ],  
  imports: [  
    BrowserModule,  
    AppRoutingModule,  
    HttpClientModule,  
    BrowserAnimationsModule,  
    MatToolbarModule,  
    MatIconModule,  
    MatButtonModule,  
    MatCardModule,  
    MatProgressBarModule  
  ],  
  providers: [],  
  bootstrap: [AppComponent]  
})  
export class AppModule { }

Step 3 — Calling the Angular 9 Upload Service

In this step, let’s implement the UI for uploading images to a server.

Go to the src/app/home/home.component.ts file, and start by adding the following imports:

import { Component, OnInit, ViewChild, ElementRef  } from '@angular/core';
import { HttpEventType, HttpErrorResponse } from '@angular/common/http';
import { map } from 'rxjs/operators';  
import { UploadService } from  '../upload.service';

Next, add the fileInput reference and files array and inject the UploadService via the component constructor as follows:

@Component({  
  selector: 'app-home',  
  templateUrl: './home.component.html',  
  styleUrls: ['./home.component.css']  
})  
export class HomeComponent implements OnInit {
    @ViewChild("fileInput", {static: false}) fileInput: ElementRef;
    files  = [];  
    constructor(private uploadService: UploadService) { }

Next, add the callUploadService() method as follows:

callUploadService(file) {  
    const formData = new FormData();  
    formData.append('file', file.data);  
    file.inProgress = true;  
    this.uploadService.upload(formData).pipe(  
      map(event => {  
        switch (event.type) {  
          case HttpEventType.UploadProgress:  
            file.progress = Math.round(event.loaded * 100 / event.total);  
            break;  
          case HttpEventType.Response:  
            return event;  
        }  
      }).subscribe((event: any) => {  
        if (typeof (event) === 'object') {  
          console.log(event.body);  
        }  
      });  
  }

We simply make a FormData instance and append our file to a file field.

Please note that you can name the file field with any valid key name but you need be aware that you should use the same name in the backend server for extracting the file data.

Next, we call the upload() method of the UploadService.

Next, we need to add an upload() method for uploading multiple image files with FormData:

private upload() {  
    this.fileInput.nativeElement.value = '';  
    this.files.forEach(file => {  
      this.callUploadService(file);  
    });  
}

Next, add the onClick() method as follows:

onClick() {  
    const fileInput = this.fileInput.nativeElement;
    fileInput .onchange = () => {  
        for (let index = 0; index < fileInput .files.length; index++)  
        {  
             const file = fileInput .files[index];  
             this.files.push({ data: file, inProgress: false, progress: 0});  
        }  
          this.upload();  
    };  
    fileInput.click();  
}

Step 4 — Creating the HTML Template with Material Icon, Card, Button, and ProgressBar Components

In this step, we'll buid the HTML template for uploading files.

Go to the src/app/home/home.component.html file and add the following markup:

<div><mat-card>  
        <mat-card-content>  
            <ul>  
                <li *ngFor="let file of files">  
                    <mat-progress-bar [value]="file.progress"></mat-progress-bar>  
                    <span id="file-label">  

                    </span>  
                </li>  
            </ul>  
        </mat-card-content>  
        <mat-card-actions>  
            <button mat-button color="warn" (click)="onClick()">  
                <mat-icon>file_upload</mat-icon>  
                Upload  
            </button>  
        </mat-card-actions>  
    </mat-card><input type="file" #fileInput id="fileUpload" name="fileUpload" multiple="multiple" accept="image/*" style="display:none;" /></div>

We loop over the files using the ngFor directive.

Conclusion

In this how-to post, we've seen how to build an UI for uploading multiple files with Angular 9 Material components such as MatProgressBar, MatIcon, MatCard, and MatButton.


Sponsored Links