When implementing a custom uploadHandler, the PrimeNG File Upload Progress may not accurately reflect the upload progress

Exploring the capabilities of the PrimeNG File Upload Component

I have customized the upload process to connect with an API using a special uploadHandler as shown below:

<p-fileUpload #fileUpload name="fileUpload" 
              (uploadHandler)="uploadHandler($event)" customUpload="true" fileLimit="5"
              multiple="multiple" accept="image/*" maxFileSize="1000000">
</p-fileUpload>

In my component.ts, I call upon the following functionality:

uploadedFiles: any[] = [];
@ViewChild('fileUpload') fileUpload: any;

constructor(private wpService: WordpressService, private cd: ChangeDetectorRef) {}

async uploadHandler(event) {
    console.log(this.fileUpload)
    this.fileUpload.disable = false;
    this.fileUpload.progress = 5;
    this.fileUpload.onProgress.emit({progress: this.fileUpload.progress});
    this.cd.detectChanges();
    this.uploadedFiles = [];

    const perFilePercent = 95 / event.files.length;
    this.fileUpload.disable = true;
    for (const f of event.files) {
        await this.wpService.uploadFile(f).then(response  => {
            const thisFile = f;
            thisFile.id = response.id;
            thisFile.url = response.source_url;
            this.fileUpload.progress += perFilePercent;
            this.fileUpload.onProgress.emit({progress: this.fileUpload.progress});
            this.cd.detectChanges();
            this.uploadedFiles.push(thisFile);
    });
    }

    this.fileUpload.files = [];
    this.cd.detectChanges();
}

Encountering an issue where manual updates to this.fileUpload.progress and

this.fileUpload.onProgress.emit({progress: this.fileUpload.progress});
are not reflected in the file upload component itself.

Interestingly, binding a progress bar to this.fileUpload.progress outside of the component works fine. For instance:

<p-progressBar [value]="fileUpload.progress" [showValue]="false"></p-progressBar>

Causes the expected behavior, while the progress bar within the actual file upload component remains static after the initial update.

A video demonstrating this behavior can be viewed at:

There seems to be an issue with updating the viewchild values or the event emitter, but the exact problem and solution remain elusive.

Answer №1

Although this post is old, I recently encountered a similar task and wanted to share how I tackled it:

/*before constructor*/

totalPercent = 0;
percentDone: number;
@ViewChild('primeFileUpload') primeFileUpload: FileUpload;
private percentDonePerFile: number;

async fileUpload($event) {
    if ($event && $event.files) {
      this.totalPercent = $event.files.length * 100;
      this.percentDone = 0;
      console.log('uploading..');
      let sub;
      let i = 1;
      for (const file of $event.files) {
        const path = '/my/super/path';
        sub = this.docService.percentSub.subscribe(perc => {
          this.percentDonePerFile = perc;
          this.percentDone = (i - 1) * 100 + this.percentDonePerFile;
          console.log('emitting: ' + (this.percentDone / this.totalPercent * 100));
          this.primeFileUpload.onProgress.emit(this.round(this.percentDone / this.totalPercent * 100));
        });
        const dummyEvent = {srcElement: {files: [file]}};
        await this.docService.uploadFile(dummyEvent, path);
        this.percentDone = i * 100;
        this.primeFileUpload.onProgress.emit(this.round(this.percentDone / this.totalPercent * 100));
        console.log('emitting: ' + (this.percentDone / this.totalPercent * 100));
        sub.unsubscribe();
        i++;
      }
    }
  }

  progressReport($event: any) {
    this.primeFileUpload.progress = $event;
  }

My HTML code is simple:

      <p-fileUpload customUpload="true" #primeFileUpload
                multiple="true" (onProgress)="progressReport($event)"
                accept="image/*" maxFileSize="2000000" (uploadHandler)="fileUpload($event)"></p-fileUpload>

Hopefully this solution can be useful to someone! Have a wonderful day.

Answer №2

This solution worked well for me, especially since the API has been updated.

HTML Code Snippet

<div class="card flex justify-content-center">
    <p-toast />
    <p-fileUpload #fileUploaderForm name="demo[]" [multiple]="false" customUpload="true"
        (uploadHandler)="handleFileUpload($event, fileUploaderForm)"
        (onProgress)="onProgress($event, fileUploaderForm)">
        <ng-template pTemplate="content">
            <ul *ngIf="uploadedFiles.length">
                <li *ngFor="let file of uploadedFiles">
                    {{ file.name }} - {{ file.size }} bytes
                </li>
            </ul>
        </ng-template>
    </p-fileUpload>
</div>

TypeScript/JavaScript Code Snippet

uploadedFiles: any[] = [];

  constructor(private messageService: MessageService) { }

  async handleFileUpload(event: FileUploadHandlerEvent, fileUploadForm: FileUpload) {
    console.log('Handling file upload', event, fileUploadForm);

    try {
      const result = await uploadData({
        path: `upload/${event.files[0].name}`,
        data: event.files[0],
        options: {

          onProgress: (progress) => {
            const progressPct = Math.round(progress.transferredBytes / progress.totalBytes! * 100)
            fileUploadForm.onProgress.emit({
              originalEvent: undefined!,
              progress: progressPct
            });
          }
        }
      }).result;
      this.messageService.add({ severity: 'success', summary: 'Success', detail: 'File Uploaded', life: 3000 });
      fileUploadForm.clear();
      this.uploadedFiles.push(event.files[0]);

    } catch (error) {
      console.log('Error : ', error);
    }
  }
  onProgress(event: FileProgressEvent, fileUploadForm: FileUpload) {
    fileUploadForm.progress = event.progress;
  }

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

What is the advantage of utilizing the "extends" keyword over directly stating the type?

Recently, I came across this interesting article at https://www.typescriptlang.org/docs/handbook/generics.html#generic-constraints I can't help but wonder why the extends keyword is necessary in this context. interface Lengthwise { length: number; ...

Setting up an nginx configuration that seamlessly integrates an Angular 4 application and a WordPress blog within the same route

Presumption: The current system is hosted on https://example.com [which is statically served from /home/centos/projects/dist.example.com] My attempt was to set up the path https://example.com/blogs to run a WordPress blog application. This is my conf ...

Using *ngIf to verify the presence of an attribute

Currently working with Angular2 and trying to implement a condition to display something. For instance, if group.permissions=Can Create File, then something should appear on the page. This is the code I have written so far: <div class="col-md-9" *ngI ...

I am seeking guidance for developing my own messaging platform, similar to Discord, using Typescript

Allow me to simplify this for you. This piece of code outlines TypeScript interfaces and namespaces for a WebSocket API that is commonly used in a chat or messaging system. It seems to define the format of messages being exchanged between a client and ser ...

The BehaviorSubject will consistently emit identical values to each subscription

I am currently facing an issue with the BehaviorSubject where it emits a value for every subscription. This means that if I have, for example, 2 subscriptions to this.projectService.projectState$ streams using methods like async or tap, the projectState$ e ...

I am curious about utilizing Primeng's MegaMenu component and how I can ensure that my nested menu options properly work with the "routerLink" functionality

Hello, thank you for taking the time to read this message. I want to make it clear that I am new to primeNg and not an expert in Angular either. Overall, the menu is appearing as expected and functioning well. However, I am facing an issue with the dropd ...

Is it necessary for me to cancel subscriptions in my unit tests?

In the scenario where I have a test like the one provided below: it('should return some observable', async(() => { mockBackend.connections.subscribe((mockConnection: MockConnection) => { const responseOptions = new ResponseOptions({ ...

Steps to resolve the npm ERR! code ELIFECYCLE error when deploying to Heroku

After dedicating time to learning Angular on my own, I recently started a project. I completed my code, prepared it for deployment on Heroku, and attempted to deploy it. Unfortunately, I encountered the following error: -----> Build Detected both &qu ...

Interacting between components using Angular 2 services

I am attempting to implement bidirectional service communication using Angular. I have followed the instructions provided in the documentation here: https://angular.io/docs/ts/latest/cookbook/component-communication.html#!#bidirectional-service interactio ...

Creating an interface that extends the Map object in TypeScript to maintain the order of keys

After learning that the normal object doesn't preserve key order in TypeScript, I was advised to use Map. Nevertheless, I'm struggling to figure out how to assign values once I've declared the interface. Take a look at my approach: Coding ...

Encountering an issue where attempting to access the `toUpperCase` property of undefined in an *ngFor loop leads to an error

I encountered an issue when trying to specify an index in *ngFor, as I received a type error with the following message: <div class='text' *ngFor='let item of blogs; let i = index | async | filter : 'feat' : true'> Rem ...

Importing dynamically into Ionic 2 from locations other than the "node_modules" directory

I've recently reviewed the documentation for ModuleResolution in TypeScript on this page: https://www.typescriptlang.org/docs/handbook/module-resolution.html#node My understanding is that all files I wish to import must reside within the node_modules ...

Accessing JSON data stored locally and initializing it into a TypeScript variable within a React application

I'm new to working with JSON arrays and I'm facing a challenge. I am looking for a way to load data from a JSON file into a Typescript variable so that I can perform a specific operation that involves arrays. However, I'm unsure of how to ac ...

What could be the reason for Typescript attempting to interpret files in the `./build` directory as input files?

After struggling for an hour on this issue, I am stuck. The variables outDir and rootDir are set. However, the problem arises when only src is included in include, TypeScript shows the configuration via showConfig, yet it's attempting to compile 4 fi ...

Click on the button to sort Angular data

Greetings! I am a newcomer trying to grasp the concepts of angularjs/typescript. I have compiled an array of fruits, displayed in an unordered list. My goal is to arrange them in descending order and implement a reverse search function to display the item ...

What is the best way to incorporate Ekko Lightbox into an Angular 7 Project?

I'm facing an issue while implementing Ekko lightbox in my angular project. Specifically, I want to use it in a certain component but I am unsure about how to import the necessary files into that component. After installing Ekko via NPM, I found all ...

Tips for creating basic Jasmine and Karma tests for an Angular application to add an object to an array of objects

I have developed a basic Angular project for managing employee data and I'm looking to test the addProduct function. Can someone guide me on how to write a test case for this scenario? I am not using a service, just a simple push operation. Any assist ...

What is the process of invoking a service from a controller?

In my MovieSearchCtrl controller class, I have a method called returnMovies(query) that looks like this: returnMovies(query): any { return MovieSeat.MovieSearchService.getMovies(query); } Within the MovieSearchService service class, there is a functi ...

Remove the package from the @types folder within the node_modules directory

I currently have the 'mime' library in my node_modules directory and I am looking to completely remove it from my project, along with its @types files. The reason for this is that the old mime package is not functioning correctly for me, so I wan ...

What is the best way to retrieve the most recent emitted value using a BehaviorSubject in a different component?

When using BehaviorSubject, I encounter an issue where I can get the last emitted value in the same component, but after navigating to another component, I only receive the default value instead of the last emitted value. I implemented BehaviorSubject to ...