Angular Material File Upload Component Example

In this Angular Material tutorial, we’re going to learn How to add a File Browse button with an Input text field to show names of files selected by using the Material library components.

When using the Material UI components in the Angular project to create a Form, we always miss control for uploading a file.

Like in Bootstrap there is a customized control, which can be used in place of an Input: file. This looks like this

 

To add a similar Form control, I tried to create a mix of a few Material components to have something similar. So I created this

Let’s quickly check how to build this file browse control in Angular using Material components.

Importing Material Components

To create a Browse component package, we need to import a few Material component modules, including MatToolbarModule, MatButtonModule, MatFormFieldModule and MatInputModule

After updating the app.module.ts file will look like this

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';

import { AppComponent } from './app.component';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';

import { FormsModule } from '@angular/forms';

import { MatButtonModule } from '@angular/material/button';
import { MatToolbarModule } from '@angular/material/toolbar';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatInputModule } from '@angular/material/input';


@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [

    FormsModule,
    BrowserModule,
    BrowserAnimationsModule,

    MatToolbarModule,
    MatButtonModule,
    MatFormFieldModule,
    MatInputModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

 

Adding Form with Browse File Button

In the template add the following <mat-form-field />

<mat-form-field>

    <div class="myfilebrowser">

      <mat-toolbar>

        <!-- Readonly Input to show File names -->
        <input matInput [(ngModel)]="myfilename" readonly name="memberContactNo" />

        <!-- Browse Button -->
        <button mat-flat-button color="primary">
          Browse
        </button>

      </mat-toolbar>

      <!-- Fetch selected filed on change -->
      <input type="file" #UploadFileInput id="fileUpload" (change)="fileChangeEvent($event)" name="fileUpload"
        multiple="multiple" accept="image/*" />

    </div>

</mat-form-field>

Here we have a <mat-toolbar> to align a text field with readOnly and button control. They are wrapped inside a div with class="myfilebrowser" to add some custom style.

The <input type="file" /> control is placed on the top of the text field and button by using position:absolute; , so that whenever a user clicks, the file selection window will open.

The input: file control is having (change) event listener to fetch selected files and update the input: text filed with file names.

There is also a template variable #UploadFileInput to reset any previous file selected to enable a user to select a previously selected file again otherwise which is not possible.

 

Update the Component Class

In the component class, we’ll add the method called on (change) event

import { Component, ViewChild, ElementRef } from '@angular/core';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss']
})
export class AppComponent {
  title = 'angular-material-file-upload-app';

  @ViewChild('UploadFileInput') uploadFileInput: ElementRef;
  myfilename = 'Select File';


  fileChangeEvent(fileInput: any) {

    if (fileInput.target.files && fileInput.target.files[0]) {


      this.myfilename = '';
      Array.from(fileInput.target.files).forEach((file: File) => {
        console.log(file);
        this.myfilename += file.name + ',';
      });

      const reader = new FileReader();
      reader.onload = (e: any) => {
        const image = new Image();
        image.src = e.target.result;
        image.onload = rs => {

          // Return Base64 Data URL
          const imgBase64Path = e.target.result;

        };
      };
      reader.readAsDataURL(fileInput.target.files[0]);

      // Reset File Input to Selct Same file again
      this.uploadFileInput.nativeElement.value = "";
    } else {
      this.myfilename = 'Select File';
    }
  }

}

You can handle events inside the fileChangeEvent method like uploading the file straight away or set model to upload when the complete form is submitted.

 

Add CSS Style

There is also a small CSS custom code to position the input:file button and a few arrangements for the toolbar component.

.myform-wrapper {
    margin: 50px;
    width: 350px;

    .mat-form-field {
        width: 100%;
    }

    .mat-toolbar-single-row {
        height: auto !important;
        background: transparent;

        button {
            width: 30%;
        }
    }
}

#fileUpload {
    position: absolute;
    z-index: 9;
    opacity: 0;
    height: 100%;
    width: 100%;
    left: 0px;
    top: 0px;
    cursor: pointer;
}

 

The file browse control we created can be easily used with other elements to match the style

 

 

Conclusion

We managed to create a File Browse control using Material components which can be used to mix with other form controls easily. You can also check this post on how to upload file in base64 format with validation of file size and file type.

 

Leave a Comment

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