Need Help With Angular Development?

Work with our skilled Angular developers to accelerate your project and boost its performance.

Hire Angular Developers

Support On Demand!

This document provides code examples for implementing file upload functionality in Angular applications with a Web API backend, covering different Angular versions.

HTML Template (Same for all versions)




Angular 17 (Latest)

@Component({ standalone: true, imports: [CommonModule] })
export class FileUploadComponent {
  private http = inject(HttpClient);
  selectedFiles: File[] = [];
  uploadProgress = 0;

  onFileSelected(event: Event) {
    const input = event.target as HTMLInputElement;
    this.selectedFiles = input.files ? Array.from(input.files) : [];
  }
  uploadFiles() {
    const formData = new FormData();
    this.selectedFiles.forEach(file => formData.append('files', file));

    this.http.post('/api/upload', formData, {
      reportProgress: true,
      observe: 'events'
    }).subscribe({
      next: (event) => {
        if (event.type === HttpEventType.UploadProgress && event.total) {
          this.uploadProgress = Math.round((100 * event.loaded) / event.total);
        }
      },
      error: (err) => console.error(err)
    });
  }
}

Angular 15-16

@Component({ /* NgModule-based */ })
export class FileUploadComponent {
  constructor(private http: HttpClient) {}
  selectedFiles: File[] = [];

  onFileSelected(event: any) {
    this.selectedFiles = Array.from(event.target.files);
  }
  uploadFiles() {
    const formData = new FormData();
    this.selectedFiles.forEach(file => formData.append('files', file));

    this.http.post('/api/upload', formData, {
      reportProgress: true,
      observe: 'events'
    }).subscribe({
      next: (event) => { /* Same as Angular 17 */ },
      error: (err) => console.error(err)
    });
  }
}

Angular 12-14

@Component({ /* NgModule-based */ })
export class FileUploadComponent {
  constructor(private http: HttpClient) {}
  selectedFiles: FileList | null = null;
  onFileSelected(event: any) {
    this.selectedFiles = event.target.files;
  }
  uploadFiles() {
    if (!this.selectedFiles) return;
    const formData = new FormData();
    Array.from(this.selectedFiles).forEach(file => formData.append('files', file));

    this.http.post('/api/upload', formData, {
      reportProgress: true,
      observe: 'events'
    }).subscribe(
      (event) => { /* Same progress handling */ },
      (err) => console.error(err)
    );
  }
}

Angular 2-11

@Component({ /* NgModule-based */ })
export class FileUploadComponent {
  constructor(private http: HttpClient) {}
  selectedFiles: FileList | null = null;

  onFileSelected(event: any) {
    this.selectedFiles = event.target.files;
  }
  uploadFiles() {
    if (!this.selectedFiles) return;
    const formData = new FormData();
    for (let i = 0; i < this.selectedFiles.length; i++) {
      formData.append('files', this.selectedFiles[i]);
    }
    this.http.post('/api/upload', formData, {
      reportProgress: true,
      observe: 'events'
    }).subscribe(
      (event) => { /* Same progress handling */ },
      (err) => console.error(err)
    );
  }
}

Key Differences

1. Angular 17 (Latest)

  • Standalone Components: No NgModule required. Uses standalone: true.
  • Modern Injection: inject(HttpClient) replaces constructor-based DI.
  • Strict Typing: Event targets use type assertions (as HTMLInputElement).
  • Observable Syntax: Uses subscribe({ next, error }) for cleaner error handling.

Code Impact:

// Component definition
@Component({ standalone: true, imports: [CommonModule] })

// File selection (strict typing)
onFileSelected(event: Event) {
  const input = event.target as HTMLInputElement;
  this.selectedFiles = input.files ? Array.from(input.files) : [];
}

2. Angular 15-16

  • Optional Standalone: Supports both NgModule and (from v15+) standalone.
  • Improved HTTP Client: Stronger type inference for HttpEventType.
  • Null Safety: Stricter checks for FileList handling.

Code Impact:

// Uses constructor DI (like older versions)
constructor(private http: HttpClient) {}

// FileList conversion (explicit null checks)
if (!event.target.files) return;
this.selectedFiles = Array.from(event.target.files);

3. Angular 12-14

  • Strict Mode Default: Forces null checks (strictTemplates, strictNullChecks).
  • Ivy Renderer: Better performance but may break legacy View Engine code.
  • Modern Iteration: Prefers Array.from() over for loops.

Code Impact:

// Mandatory null checks
selectedFiles: FileList | null = null;

// Safer event handling
if (event.type === HttpEventType.UploadProgress && event.total) { 
  // TypeScript knows `event.total` exists
}

4. Angular 2-11 (Legacy)

  • View Engine: Older rendering pipeline (slower, less optimized).
  • Loose Typing: Frequent use of any for events (event: any).
  • Manual Checks: No strict mode; runtime errors possible.

Code Impact:

// Legacy FileList handling
selectedFiles: FileList; // No strict null checks

// Manual type assertions for HTTP progress
if (event.type === HttpEventType.UploadProgress) {
  const progress = (event.loaded / (event as any).total) * 100;
}

Related Q&A