Search code examples
angulartypescriptfile-upload

In Angular, how to clear the file upload text box after the file is uploaded


HTML

<div class="row">
    <div class="mb-6">
        <label class="form-label" for="defaultFile">Upload file</label>
        <input type="file" class="form-control" id="defaultFile" (change)="onChange($event)">
        <hr>
        <button type="button" class="btn btn-outline-theme" (click)="uploadFile()">Upload</button>
   </div>
</div>

Typescript

import { Component } from '@angular/core';
import { HttpClient } from '@angular/common/http';

@Component({
  selector: 'app-file-upload',
  templateUrl: './file-upload.component.html',
  styleUrl: './file-upload.component.scss'
})
export class FileUploadComponent {
    fileToUpload: File | null = null;

    constructor(private http: HttpClient) { }

    onChange(event:any) {
        this.fileToUpload = event.target.files[0];
    }

    uploadFile() {
        if (!this.fileToUpload) {
            alert('No file selected.');
            return;
        }

        const formData: FormData = new FormData();
        formData.append('file', this.fileToUpload, this.fileToUpload.name);

        return this.http.post("<ENDPOINT TO UPLOAD THE FILE>", formData).subscribe(
            (response) => {
                console.log(response);
            },
            (error) => {
                console.error(error);
            }
        );
    }
}

The file upload works fine. Not sure what's the "angular" way to get the text box to clear. (To keep this post simple, I have moved the code that calls API to component and removed all the error handling, etc. to capture the gist.)


Solution

  • To keep it simple, we can use template reference variable #input in html, to pass the element reference into the function and clear the value, using input.value = null

    To keep it simple I removed the API calls and replaced them with of(true) to mock and API call!

    import { HttpClient } from '@angular/common/http';
    import { Component } from '@angular/core';
    import { bootstrapApplication } from '@angular/platform-browser';
    import { of } from 'rxjs';
    import 'zone.js';
    
    @Component({
      selector: 'app-root',
      standalone: true,
      template: `
        <div class="row">
            <div class="mb-6">
                <label class="form-label" for="defaultFile">Upload file</label>
                <input type="file" class="form-control" id="defaultFile" (change)="onChange($event)" #input>
                <hr>
                <button type="button" class="btn btn-outline-theme" (click)="uploadFile(input)">Upload</button>
          </div>
        </div>
      `,
    })
    export class App {
      fileToUpload: File | null = null;
    
      constructor() {}
    
      onChange(event: any) {
        this.fileToUpload = event.target.files[0];
      }
    
      uploadFile(input: any) {
        if (!this.fileToUpload) {
          alert('No file selected.');
          return;
        }
    
        const formData: FormData = new FormData();
        formData.append('file', this.fileToUpload, this.fileToUpload.name);
    
        return of(true).subscribe(
          (response: any) => {
            console.log(response);
            input.value = null; // <- changed here!
          },
          (error: any) => {
            console.error(error);
          }
        );
      }
    }
    
    bootstrapApplication(App);
    

    Stackblitz Demo