Home > Blockchain >  What makes this Angular file uploader fail when browsing for the file?
What makes this Angular file uploader fail when browsing for the file?

Time:02-01

I am working on an app in Angular 14 with includes a form. The form has a file uploader.

In form.component.ts I have:

import { Component, ElementRef, OnInit, ViewChild } from '@angular/core';
import { FormGroup, FormControl, Validators } from '@angular/forms';
import { FormService } from '../services/form.service';

@Component({
  selector: 'app-form',
  templateUrl: './form.component.html',
  styleUrls: ['./form.component.css'],
})
export class FormComponent {
  @ViewChild('fileDropRef', { static: false })
  public fileDropEl!: ElementRef;
  public files: any[] = [];

  public form: FormGroup = new FormGroup({
    first_name: new FormControl('', Validators.required),
    last_name: new FormControl('', Validators.required),
    email: new FormControl('', [Validators.required, Validators.email]),
    imageName: new FormControl(''),
  });

  constructor(private formService: FormService) {}

  ngOnInit(): void {}

  // File uploader Begin
  public onFileDropped($event: any) {
    this.prepareFilesList($event);
  }

  public fileBrowseHandler(files: any) {
    this.prepareFilesList(files);
  }

  public deleteFile(index: number) {
    if (this.files[index].progress < 100) {
      console.log('Upload in progress.');
      return;
    }
    this.files.splice(index, 1);
  }

  public uploadFilesSimulator(index: number) {
    setTimeout(() => {
      if (index === this.files.length) {
        return;
      } else {
        const progressInterval = setInterval(() => {
          if (this.files[index].progress === 100) {
            clearInterval(progressInterval);
            this.uploadFilesSimulator(index   1);
          } else {
            this.files[index].progress  = 5;
          }
        }, 200);
      }
    }, 1000);
  }

  public prepareFilesList(files: Array<any>) {
    for (const item of files) {
      item.progress = 0;
      this.files.push(item);
    }
    this.fileDropEl.nativeElement.value = '';
    this.uploadFilesSimulator(0);
  }

  public formatBytes(bytes: number, decimals: number = 2) {
    if (bytes === 0) {
      return '0 Bytes';
    }
    const k = 1024;
    const dm = decimals <= 0 ? 0 : decimals;
    const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
    const i = Math.floor(Math.log(bytes) / Math.log(k));
    return parseFloat((bytes / Math.pow(k, i)).toFixed(dm))   ' '   sizes[i];
  }
  // File uploader End

  public sendFormData() {
    this.formService
      .sendFormData(this.formService.value)
      .subscribe((response) => {});
  }
}

In the template, the file uploader looks like this:

<div >
  <div  appDnd (fileDropped)="onFileDropped($event)">
    <input formControlName="imageName" type="file" #fileDropRef id="fileDropRef" multiple />
    <div >
      <h3 >Drop your file to upload</h3>
      <h3 >or</h3>
      <label  for="fileDropRef">Browse for file</label>
    </div>
  </div>

  <div >
    <div  *ngFor="let file of files; let i = index">
      <img
        src="../../assets/images/dnd/ic-file.svg"
        alt=""
        
      />
      <div >
        <p >{{ file?.name }}</p>
        <p >{{ formatBytes(file?.size) }}</p>
        <app-progress [progress]="file?.progress"></app-progress>
      </div>
      <img
        src="../../assets/images/dnd/ic-delete-file.svg"
        
        width="20px"
        alt="file"
        (click)="deleteFile(i)"
      />
    </div>
  </div>
</div>

There is a Stackblitz HERE.

The problem

Although the file uploader works as expected when the user drags a file over it, displaying the upload progress, it fails when browsing for the file.

Questions

  1. What am I doing wrong?
  2. How can I fix the problem?

CodePudding user response:

salutare:) you need to trigger "onFileDropped" also in file selection:

   <input #inputType type="file" #fileDropRef id="fileDropRef" multiple (change)="onFileChange($event)"/>

onFileChange(event: any) {
    const files = event.target.files;
    this.onFileDropped(files);
  }

  • Related