Reading files from multiple sources using Angular's FormArray

I am facing an issue with uploading multiple images from different inputs. I have a form set up with a formArray to add a new input each time the "Add file" button is clicked.

this.designForm = this.fb.group({
      newFiles: this.fb.array([
        this.fb.control(null, Validators.required)
      ], Validators.required)
    });
  get newFiles() {
    return this.designForm.get('newFiles') as FormArray;
  }
  addNewFiles() {
    this.newFiles.push(this.fb.control(null, Validators.required));
  }

The button:

<button type="button" (click)="addNewFiles()">Add new Document</button>

The input:

<div *ngFor="let newFile of newFiles.controls; let i=index">
                    <input type="file" 
                    id="usecaseImage" 
                    (change)="showPreviewImage($event)"
                    [formControlName]="i">
                </div>

And the event method:

showPreviewImage(event: any) {
    if (event.target.files && event.target.files[0]) {
        var reader = new FileReader();
        reader.onload = (event: any) => {
          for(let i=0; i<this.newFiles.length; i++){
            console.log(this.newFiles.length);
            this.designForm.value.newFiles[i] = event.target.result; 
          }
        }
        reader.readAsDataURL(event.target.files[0]);   
    }
}

It successfully uploads the images, but when trying to preview them, it repeats the last uploaded image. For example, if I have 3 inputs with values:

input1 value-> X.JPG, input2 value-> Y.JPG and input3 value-> Z.JPG

It previews Z.JPG three times!

Edit: The preview is in another component where I retrieve data from the service:

this.designForm = this.sdlcService.designForm ;

Then I loop through the forms and their respective inputs using keyvalue pipe to extract the values.

<div *ngFor="let form of designForm ; let d = index">
              <img [src]="input.value" *ngFor="let input of form | keyvalue; let s = index">
            </div>

How can I resolve this issue?

Answer №1

Presented below is a common solution using Angular:

template

<button class="" (click)="uploader.click()">
      <input hidden type="file" multiple #uploader (change)="onFileInputChange($event)" />
</button>

ts

attachments: File[] = [];
----------------------------
onFileInputChange($event: any) {
 if (!$event.target.files) {
   return;
 }
 Array.from($event.target.files).forEach((f: File) => {
   if (!this.attachments.find((i) => i.name === f.name)) {
    this.attachments.push(f);
   }
 });
}


async onSubmit() {
   if (!this.attachments.length) {
      return;
   }

   const attachments = await Promise.all(this.attachments.map(this.fileToDataURL));        
      // add any action you want, here you got an array of dataUri
 }



fileToDataURL(file_: File) {
    const reader = new FileReader();
    // tslint:disable-next-line:no-unused
    return new Promise((resolve, reject) => {
      reader.readAsDataURL(file_);
      reader.addEventListener(
        'load',
        function (event) {
          resolve(event.target.result);
        },
        false,
      );
    });
  }

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

Resolving an inevitable circular dependency in Angular 9 that cannot be avoided

Implementing session timeout on the UI side involves a series of steps that need to be followed. Upon successful login, initiate a timeout mechanism to display a popup message. setTimeout(()=>{this.openTimeOutDialog();},expTime); After an hour, ...

In Angular code, the foreach loop jumps to the next function before completing each iteration of the loop

private processArray(evts: Event[]): Promise<void> { var auditsvc = this.auditSvc; var t = this; if (!evts || evts.length == 0) { return; } let objArr: any[] = []; evts.forEach(function (inpEvt) { auditsvc.getAuditDetails(inpEv ...

Encountered an error - 'SyntaxError: unexpected token: ':'' while attempting to load a JSON file for ngx-translate using the Karma test runner

I am currently in the process of setting up system tests for my Angular application. The app utilizes the TranslateModule (ngx-translate) in this manner: TranslateModule.forRoot({ defaultLanguage: 'de', loader: { provide: Tra ...

errors.ts:30 ERROR Error: Unhandled promise rejection: Error: No routes found for specified URL Segment: 'products,%20productId'

I'm in the process of learning Angular by following a tutorial on a website. You can find it here: https://angular.io/start/routing Everything is going smoothly so far, except for the section on routing. If I add 'products/1' to the end of ...

Tips for preventing the [Vue warn]: Injection "xxxx" not found error

My current setup involves utilizing the inject/provide pattern within the nuxt composition-api. An example of this is Component A injecting a function provided by Component B, which is the parent of Component A, as illustrated below. //Component B const t ...

Guide to incorporating external code in InversifyJS without direct control

I'm wondering if it's feasible to add classes that are not editable. Inversify seems to rely heavily on annotations and decorators, but I'm curious if there is an alternative method. ...

How can one efficiently implement a recursive dynamic expanding navigation bar in Angular, and what is the best method to toggle its menu items effectively?

I am currently developing an Angular 8 app and utilizing a bootstrap 4 layout in my project. One of the features I am working on is a menu with nested items, inspired by the Dynamic Expanding Nav Drawer example. The challenge I am encountering is that whe ...

Tips for tidying up duplicated typescript content sourced from a pre-existing library

Seeking guidance on implementing best practices and gaining a better understanding of my approach. After discovering the library react-google-calendar-api, I successfully installed it using npm in my React project. However, I wanted to expand its function ...

Tips for replacing Event Handler declared in Angular's vendor.js file?

I have a requirement to include the {passive: true} option in an existing event handler that is coded in the vendor.js file. document.addEventListener('mouseup', <handler1>); document.addEventListener('touchend', <hand ...

Evaluation of component information

We are interested in testing the ChangeDetection value on a few components, but we are having trouble accessing the component metadata easily. Thus far, we have been able to do this for pipes using the following code snippet: it('should be marked as ...

Unable to locate the module name loaded using require() function

Within my React file, I am importing a Javascript file like this (I am using Typescript): let FloDialog = require('../public/js/flo-dialog.min'); Afterwards, I declare a property for the dialog class: dialog: FloDialog = null; It is important ...

The Nx end-to-end Cypress runner ensures that values from the cypress.env.json file do not overwrite the same entries in the cypress.json environment object

Having encountered an issue with my Nx powered angular project, I am facing a situation where the values provided in a cypress.env.json file are not overriding the corresponding entries in the env object of the cypress.json configuration file. This is a n ...

Explore all Intellisense choices for Typescript Props in VS Code effortlessly

In my experience, I've noticed that to see intellisense options for a TypeScript type in VS Code, you have to start typing the attribute name. If you type "a", you'll only see options that contain "a" and nothing else. Take a look at this scree ...

How can we access child components in vanilla JavaScript without using ng2's @ViewChild or @ContentChild decorators?

Recently, I delved into the world of using ViewChildren and ContentChildren in Angular 2. It got me thinking - can these be implemented in ES6 without TypeScript annotations? The TypeScript syntax, according to the official documentation, looks something ...

Encountering error TS2305 in Visual Studio Code while working with moment.js in an example from an Angular Material

After referencing the code snippet from https://material.angular.io/components/datepicker/overview#choosing-a-date-implementation-and-date-format-settings, I encountered an issue. While the code successfully compiles and runs, Visual Studio Code flagged an ...

Tips for transfering variables from an electron application to the backend of an Angular project

My goal is to develop a website and desktop application using the same code base. However, due to some minor differences between the two platforms, I need a way for my Angular app to distinguish whether it has been called from the web or from Electron. I& ...

When selecting a different file after initially choosing one, the Javascript file upload event will return e.target as null

Currently, I have implemented file uploading using <input>. However, when attempting to change the file after already selecting one, the website crashes and states that event.target is null. <Button label="Upload S3 File"> <input ...

I don't understand what's happening with this ternary format in the Typescript function - something seems off

Exploring Typescript. While browsing through a project's codebase, I stumbled upon the following snippet and am unsure of its validity. Can anyone shed light on what this code is doing? It seems to be dealing with default values, but I'm not enti ...

When using an Angular2 application that relies on an external reference to Auth0Lock, the application encounters a NotFound error when executed

For my latest project, I decided to create an app using angular2-seed as a base. Everything was going smoothly until I tried deploying the production build on an Azure website. To my surprise, I encountered an issue when trying to load the page: > Refe ...

Error NG0300 in KendoUI Angular 17: Multiple components found with matching button tagneys

Within a different component of mine, I've implemented a KendoUI Angular Grid that includes delete buttons in the command-column: <kendo-grid-command-column [width]="40"> <ng-template kendoGridCellTemplate let-dataItem> ...