Previewing multiple selected files in Angular interface

As a newcomer to Angular, I am currently working on a feature that involves selecting multiple files and displaying their previews before uploading them to the server.

While my code works correctly when individual files are selected one at a time, it fails to render all images when multiple files are chosen simultaneously. Upon further inspection using console.log, I noticed that the reader.result for all files except the last one is null, even though the reader.onload function is being executed (with the file object being added to the array without the image URL).

I aim to implement a way to remove selected files while preserving both the files themselves and their corresponding image URLs in a FileWithImage object to maintain the correct order of previews.

In my component.ts file:

onFilesSelected(event: any): void {
    this.selectedFiles = event.target.files;

    for (let i = 0; i < this.selectedFiles.length; i++) {

      let fileWithImage: FileWithImage = {
        imageUrl: '',
        file: this.selectedFiles[i],
      };

      var reader = new FileReader();
      reader.readAsDataURL(fileWithImage.file);

      reader.onload = (event) => {
        fileWithImage.imageUrl = reader.result;

        console.log(fileWithImage.file.name);
        console.log(fileWithImage.imageUrl);
        
        this.filesWithImages.push(fileWithImage);
      };
    }
  }

And in my component.html file (for selecting and displaying images):

   <button
      type="button"
      mat-raised-button
      (click)="fileInput.click()"
      class="button"
    >
      Choose File
    </button>
    <input
      hidden
      (change)="onFilesSelected($event)"
      #fileInput
      type="file"
      accept="image/*"
      multiple="multiple"
    />
    <div *ngFor="let file of filesWithImages" class="images">
      <img
        [src]="file.imageUrl"
        height="10%"
        width="10%"
        *ngIf="file.imageUrl"
      />
    </div>

I have attempted solutions like using a flag to block the loop until reader.onload executes, as well as directly fetching the URL from a method:

createImageUrl(file: File): any {
    var reader = new FileReader();
    reader.readAsDataURL(file);

    reader.onload = (event) => {
      return reader.result;
    };
  }

But calling this method in the [src] attribute of an image tag in HTML caused my program to crash.

The primary issue seems to be why the result of the reader is null for initial files and only properly displayed for the last one. If anyone can help me identify the root cause of this problem, I would greatly appreciate it.

Answer №1

Consider modifying the reader variable to be within local scope.

Replace

var reader = new FileReader();

with

const reader = new FileReader();

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

IDE type inferences are wrong for the Polymorphic React component

declare const MyComponent = <A extends {id: bigint|number}>(props: MyProps<A>) => React.FC<{}> interface MyProps<A extends {id: number}> { data: A[] orderBy: keyof A } declare const x: { id: number, foo: string }[] const F ...

Creating a generic in Typescript that enforces an index signature

In the world of Typescript, adding an index signature to an object can be done in a couple of different ways depending on your specific requirements. Let's imagine we have an interface called Indexable and a type named EmployeeDir. type EmployeeType ...

Is it possible to send form data using the file upload function?

I've successfully implemented a file upload feature with a progress bar, and the file gets uploaded in fileUpload.php. function fileSelected() { var file = document.getElementById('fileToUpload').files[0]; if (file) { var fil ...

Exploring the method to extract a value from an array of objects using JSON parsing in Appcelerator

Visualize an artificial json response, here's the string representation of this JSON... [{"A":"1","B":{"name":"joe","lastname":"jones"},"COLORS:{"red":"rojo","blue":"azul"},"active":"yes"}] I am aiming to extract the name "joe" using the following c ...

Utilizing JavaScript AJAX to upload a dynamically generated PDF file to a specific directory on the server

Looking for a solution to save a complex table generated via JavaScript as a PDF on the server. Existing pdf generation libraries have limitations with style and fonts, making it difficult for 'complex' tables. The table can currently be download ...

Guide to using AJAX for the GraphHopper Matrix API

I am struggling to send this JSON with the required information because I keep encountering an error during the request. message: "Unsupported content type application/x-www-form-urlencoded; charset=UTF-8" status: "finished" I'm not sure what I&apos ...

Submit file in Cypress while hiding input[type="file"] from DOM

Currently, I am conducting end-to-end testing on an Angular project that utilizes Ant Design (NG-ZORRO). In this project, there is a button with the class nz-button that, when clicked, opens the file explorer just like an input type="file" element would. W ...

Preventing Multiple Form Submissions in JavaScript

I'm having an issue with my form submission to Parse where, after adding client-side validation, the data is being double submitted to the database. Despite adjusting my code based on other Stack posts and being new to JavaScript, I'm still expe ...

Unable to modify the variable within angular.js

I have been working on developing an Ionic application with angular.js and I am almost done, but I have encountered a minor issue. Inside my templates/menu.html file, I have the following code: <ion-item nav-clear menu-close ng-click="filterByPeriod(w ...

Is there a way to pre-load the content ahead of the footer?

My footer appears before the content is fully loaded. In my navbar, I have multiple buttons that open new components when clicked. When a user clicks on an event, it emits after the event data is loaded from the API and the footer loads correctly at that t ...

Having trouble parsing data in a jQuery REST call

After creating a web service using Slim Framework 3 in PHP, all data is returned using the following instruction: return $response->withJson($liste); I then created an HTML client using the "jquery.rest" plugin to view the JSON results. However, I am ...

What is a more efficient method for switching between edit mode and view mode in ng-grid?

Up until now, I've only managed to switch the edit mode in ng-grid by using separate templates and showing the correct template based on user input. For example: Plunker (resize a column and then switch to another mode) This poses a problem because ...

What is the best way to include React globally when running unit tests?

In my Rails project, I have integrated the react-rails gem, which sets up a global variable like this: window.React = React; While this is convenient for regular usage, it causes issues when running unit tests with Jest because the global React variable ...

Ways to assign values to an array within an object

I'm attempting to transfer the contents of one array into an array within an object, but I keep encountering this error: Type 'any[]' is not assignable to type '[]'. Target allows only 0 element(s) but source may have more. Here ...

Transferring Information in Angular 8 between components on the Same Level

Currently utilizing Angular 8 with two independent components. One component contains a form with an ID field, and the other is accessed by clicking a button from the first component. The second component does not display simultaneously with the first. A ...

Guide on setting up an Express application to control LED light strips with a Raspberry Pi3

After setting up a node server on my Raspberry Pi to control an Adafruit Dotstar light strip, I encountered a problem. The sequence of colors on the light strip is triggered by an HTTP request to localhost:8000/fade, causing the server to run fade.js endle ...

Every time I attempt to send a post request, I receive back only the creation date and the unique objectID

Whenever I send a post request, only the created date and objectID are returned. Whenever I send a post request, only the created date and objectID are returned. This issue persists even after multiple attempts. I attempted to verify it using Postman ...

Navigate through intricate JSON structure

Struggling with a highly complex JSON object, I am trying to list out all the properties and keys exactly as they are. While I have grasped the concept, I am having trouble with the execution. Every time the object contains another object, I need to call ...

Error message: The tag name "[email protected]" is not valid when attempting to execute npm install

I'm encountering an issue while trying to build my Angular app using Azure Continuous Integration. Right before the build step, there is an npm install process that is failing and generating the following error: Error: Invalid tag name ""<a h ...

The REST API endpoint links for Timestamp are displaying a 404 error message indicating they cannot be

After recently diving into backend development, I ran some tests locally using Postman and localhost which seemed to work perfectly. However, upon uploading my code to GitHub, I encountered a 404 error when clicking on the API endpoint hyperlinks from inde ...