I encountered an issue with my TypeScript function in Angular, as it is unable to process multiple uploaded files

I'm having trouble with my TypeScript function in Angular that is unable to read multiple uploaded files.

fileUpload(event: Event) {
    const self = this;
    this.imageUploadInp = event.target as HTMLInputElement;
    this.imageUploadInp.addEventListener("change", function () {
        for (var i = 0; i < self.imageUploadInp.files.length; i++) {
            var reader = new FileReader();
            reader.onload = function () {  
                if (reader.result != undefined) {
                    self.user.imgUrls = reader.result.toString();
                    console.log(self.user.imgUrls);
                }
            }
            reader.readAsDataURL(self.imageUploadInp.files[i]);  
        }
    });
}

Answer №1

The issue arises from the fact that the onload handler is executing asynchronously while you are constantly overwriting the reader variable within the synchronous for loop. As the for loop operates synchronously, the onload callback will only run in the subsequent cycle of the event loop. Due to variables declared with var having function scope, the reader variable in the handler function will solely reference the last image, leading to only the final image being processed.

Given your use of typescript, it's presumed that you can utilize the const/let keywords. To rectify your code, consider declaring the reader variable as const or let. Variables declared with const or let have block scope, creating new blocks on each cycle of the for loop, preventing them from overriding each other and existing independently within their respective blocks.

fileUpload(event: Event) {
    const self = this;
    this.imageUploadInp = event.target as HTMLInputElement;
    this.imageUploadInp.addEventListener("change", function () {
        for (let i = 0; i < self.imageUploadInp.files.length; i++) {
            const reader = new FileReader(); // declared as `const`
            reader.onload = function () {  
                if (reader.result != undefined) {
                    self.user.imgUrls = reader.result.toString();
                    console.log(self.user.imgUrls);
                }
            }
            reader.readAsDataURL(self.imageUploadInp.files[i]);  
        }
    });
}

I've also changed the declaration of the i variable to let within the for loop. This decision ensures that any use of the var i variable inside the onload handler won't face the same fate as the var reader, which becomes equal to

self.imageUploadInp.files.length - 1
after the completion of the for loop.

If circumstances prevent you from using let/const, another approach involves creating unique functions for each cycle of the for loop to encapsulate var reader within different function scopes:

fileUpload(event: Event) {
    const self = this;
    this.imageUploadInp = event.target as HTMLInputElement;
    this.imageUploadInp.addEventListener("change", function () {
        for (var i = 0; i < self.imageUploadInp.files.length; i++) {
            (function () { // creating different function scopes on each cycle
                var reader = new FileReader();
                reader.onload = function () {  
                    if (reader.result != undefined) {
                        self.user.imgUrls = reader.result.toString();
                        console.log(self.user.imgUrls);
                    }
                }
                reader.readAsDataURL(self.imageUploadInp.files[i]);
            }());  
        }
    });
}

In this updated version, I've utilized the IIFE pattern to isolate each reader variable created in the for loop within its distinct function scope.

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

Throw TypeError: The `pipe` property of `ngrx/store` is undefined during testing

Here is the code snippet from my TypeScript file: this.store.pipe(select(subscribe.getRegCategories)).pipe(takeUntil(this.ngUnsubscribe)).subscribe(data => { if (data && data.length) { this.allRegCategories = data; ...

Can you please tell me the location of the sqlite database file in Ionic 2 Cordova?

Currently, I am working with cordova-plugin-sqlite within the context of angular2 ionic2. Interestingly, despite my efforts, I have not been able to locate the database file anywhere within my project structure. Numerous attempts to resolve this issue by ...

Unique Version: Some effective tips for utilizing a fork of type definition such as @types

Currently, I am utilizing Typescript 2.0 along with @types and the experience has been quite positive. Thanks to @types, we can easily leverage type definitions by simply installing the package via npm. Surprisingly, I have not delved into how it actually ...

Error: Cannot modify the constant property 'name' of the function."&squo;

As I attempted to enter text into the input box, an error message appeared after typing my first letter stating "cannot assign to read only property". Below is the code I am referring to: The code of the component can be found here: This is the specifie ...

Showing records from Firebase that are still within the date range

I'm currently developing an application that allows users to book appointments on specific dates. After booking, I want the user to only be able to view appointments that are scheduled for future dates. I've attempted to compare the date of each ...

A More Straightforward Approach to Unsubscribing from Observables in Angular 7

Is there a way to simplify the process of automatically unsubscribing from Observables when a component is destroyed using takeUntil? It becomes tedious having to repeat the same code in multiple components. I am looking for a solution that allows me to a ...

Leveraging the power of Bootstrap in combination with Angular 2, integrate both ng-bootstrap and the traditional Bootstrap to enhance

Beginning a fresh Angular 2 Project, I am inclined to incorporate Bootstrap 3 for the user interface. What would be the most advisable approach in this scenario? Is it feasible to blend ng-bootstrap and the original Bootstrap components? I noticed that th ...

Obtain the filter criteria within the user interface of a Kendo grid

My Kendo grid looks like this: <kendo-grid [data]="gridData" [pageSize]="state.take" [skip]="state.skip" [sort]="state.sort" [filter]="state.filter" filterable="menu" (dataStateChange)="dataStateChange($event)" > In the ...

ABP's Angular DateTimePicker Component for Effortless Date and Time

I am experiencing an issue with a DateTime field that is supposed to display only the time: HTML: <div class='input-group date'> <input class="form-control" type="datetime" #RequiredByDate name="RequiredByDate" [value]="formatDate(h ...

Solving the issue of interconnected promises in Angular services

I am utilizing a DynamoDB service within my Angular project which returns a promise through a series of promises. This process involves retrieving a subId from Cognito and then passing that subId to a DynamoDB get query: async getUserObject(): Promise< ...

React components need to refresh after fetching data from an API

I am currently working on a React application using TypeScript and integrating JSONPlaceholder for simulating API calls. I have successfully set up everything I need, but I am encountering an issue with re-rendering components that display response data fr ...

In TypeScript, there is a curious phenomenon where private properties seem to be mimicking the

Here is an example of an issue I encountered while working with private properties in TypeScript. I expected that only the public properties would be visible in my object output, similar to normal encapsulation. My aim here is to include the property wit ...

Inactive function

I have a function that inserts my articles and I call this function on my page. There are no errors, but the next function retrieveAllArticles() is not being executed. public saveAllArticles(article) { for(let data in article) { this.db.exec ...

Reach out to the property via phone if it is listed in the JSON

When receiving JSON data from the server, I come across two different structures: JSON 1: { [{ name : 'sample1', code:'sample code 1', data : { display :'test' } ...

Excessive notification events are currently causing a blockage in the Angular app

Currently, I am utilizing Angular 7 in combination with SignalR on the backend for push notifications. At certain times, an overwhelming amount of notifications flood in, causing my application to become completely unresponsive. The SignalR service compon ...

What is the correct way to nest multiple ng-if statements?

I'm currently grappling with a problem involving multiple nested ngIf directives applied to ng-template elements in Angular.js, and I've yet to find the ideal solution. While I am aware of workarounds, they are not as efficient as I would like th ...

Implementing HTTPS Signed Certificates with IIS on Express for Production Environments

When it comes to managing API (HTTPS) certs in a development environment compared to production in an Express application running on a Node.js/Angular setup deployed to Windows IIS, the process can be a bit confusing. While proxy rewrites have been suggest ...

What causes the presence of undefined elements within the ngOnInit function of Angular?

When I initialize a library in my ngOnInit method like this: ngOnInit() { this.$grid = jQuery('.grid').masonry({ // options itemSelector: '.grid-item',//, columnWidth: 384, gutter: 24 }); ...... } and then call the method from ...

The TS2345 error is triggered when using the fs.readFile function with specified string and

Attempting to utilize the fs.readFile method in TypeScript, my code looks like this... import {readFile} from 'fs'; let str = await readFile('my.file', 'utf8'); This results in the following error message: TS2345: Argumen ...

Is it possible to utilize an array of numbers as a data source in ng2-smart table?

Hey there, I'm currently facing an issue with populating ng2-smart-table with an array of numbers. When I try to display the table, all I see is 6 empty rows like this: https://i.stack.imgur.com/DZJjq.png Here's the code for the table: <ng2- ...