Issue with handling multiple input files in an *ngFor loop

I am facing difficulties in targeting the correct input within a *ngFor loop. When I include an image with the first input (Certificat dimmatriculation), it displays a placeholder image and a delete button to reset the input, but it appears under both divs.

I specifically want to target only the input where the actual image is added. Despite having ViewChild, I am unable to make it function as intended.

View image here

Here is the code snippet:

<div class="files">
     <div class="single-file" *ngFor="let file of files">
          <h5>{{file.title}}</h5>
          <input type="file" name="file" id="{{file.slug}}" class="inputfile" #fileInput (change)="addFile(fileInput.files[0])" />
          <label for="{{file.slug}}" *ngIf="!hasFile || isDeleted">
          <img class="d-none d-xl-inline-block" src="assets/images/addImg.png" alt="">
          Ajouter votre photo
          <img class="d-block d-xl-none" src="assets/images/addImg_big.png" alt="">
     </label>
     <div class="placeholder" *ngIf="hasFile && !isDeleted">
          <img [src]="imageUrl" />
      </div>
      <div class="deleteImg" *ngIf="hasFile && !isDeleted" (click)="deleteFile()">
          <div class="btn btn-outline"><img src="assets/images/delete-x-icon.png" alt="Supprimer">Supprimer</div>
          </div>
     </div>
</div>

Furthermore, in the .ts file:

I have declared all necessary variables


file: File;
imageUrl: string | ArrayBuffer = '../app/assets/images/imgAdded.png';
hasFile = false;
isDeleted = false;

@ViewChild('fileInput', { static: false }) myFileInput: ElementRef;

files: any = [{
    'title': 'Certificat dimmatriculation',
    'slug': 'immatriculation',
    'input': '#fileInput1'
}, {
    'title': 'Preuve dassurance',
    'slug': 'insurance',
    'input': '#fileInput2'
}];

addFile(file: File) {
    if (file) {
        this.hasFile = !this.hasFile;
        // this.fileName = file.name;
        this.file = file;

        const reader = new FileReader();
        reader.readAsDataURL(file);

        reader.onload = event => {
            this.imageUrl = this.imageUrl;
            // this.imageUrl = reader.result;
        };
    }
}

deleteFile() {
    this.isDeleted = !this.isDeleted;
    this.myFileInput.nativeElement.value = '';
}

Answer №1

Right now, you're facing an issue where you're trying to handle individual file properties using component-level properties. My suggestion would be to utilize file properties for storing uploaded image data instead. This way, all actions can be targeted towards the specific file instances.

To simplify things, I've adjusted your code examples for demonstration purposes and to illustrate the approach I've taken.

In my implementation, I use a property called imageUrl on each file to hold the URL of the uploaded image data. The presence of a value in this property indicates that an image has been uploaded, and it gets cleared when the image is deleted.

component.html

<div *ngFor="let file of files">
  <h5>{{file.title}}</h5>    
  <label *ngIf="!file.imageUrl">
    <input type="file" (change)="addFile(file, $event)" />
    Add your photo
  </label>  
  <ng-container *ngIf="file.imageUrl">
    <img [src]="file.imageUrl" />
    <button (click)="deleteFile(file)">Delete</button>
  </ng-container>
</div>

Now, all operations are carried out on the individual file objects and need to be passed into the event handlers. Alternatively, you could use an array index instead of the object reference.

There might also be some confusion between the file instances and the file uploaded from the input. If feasible, consider renaming your variables files and file to something else, reserving file solely for interactions with the file input.

component.ts

addFile(file, event) {
  const uploaded = event.target.files[0];
  if (!uploaded) {
    return;
  }

  const reader = new FileReader();
  reader.onload = () => {
    file.imageUrl = reader.result;
  };

  reader.readAsDataURL(uploaded);
}

deleteFile(file) {
  file.imageUrl = '';
}

DEMO: https://stackblitz.com/edit/angular-bcgwrq

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

Jasmine-ts is encountering a problem related to a subpath within a package, causing

Embarking on a journey of jasmine unit testing, I am encountering challenges when trying to run jasmine and locate my TypeScript written specs. Using jasmine-ts, I typically execute the following command: jasmine-ts --config=spec/support/jasmine.json The ...

What kind of impact does the question mark at the conclusion of a function title make?

I came across the following TypeScript code snippet: class Foo { start?(): void {} } What caught my attention was the ? at the end of start. It appears to be making the function optional (but how can a function be optional and when would you need tha ...

Oops! An issue occurred during the `ng build` command, indicating a ReferenceError with the message "Buffer is not defined

I'm facing an issue while trying to utilize Buffer in my angular component ts for encoding the Authorization string. Even after attempting npm i @types/node and adding "node" to types field in tsconfig.json, it still doesn't compile with ng buil ...

What steps are involved in creating a local unleash client for feature flagging?

Currently attempting to implement a feature flag for a Typescript project using code from the Unleash Client. Here is where I am creating and connecting to an instance of unleash with a local unleash setup as outlined in this documentation: Unleash GitHub ...

Exploring the Functionality of the MatSlideToggleChange Event in the mat-slide-toggle Component

I want to create a form that switches between two dropdown menus using a switch. Is it possible to use the MatSlideToggleChange event from the MatSlide class to make this happen? ...

Getting exported members through Typescript Compiler API can be achieved by following these steps:

I am currently working on a project hosted at https://github.com/GooGee/Code-Builder This particular file is being loaded by the Typescript Compiler API: import * as fs from 'fs' Below is a snippet of my code: function getExportList(node: t ...

Steps for making a "confirm" button within a modal that includes a redirect URL

I have developed a modal that, upon clicking on the confirm button, should redirect the user to the page titled securities-in-portfolio. modal <div class="modal-footer justify-content-center"> <button type="button" class ...

Using interpolation brackets in Angular2 for variables instead of dots

I'm curious if Angular2 has a feature similar to the bracket notation in Javascript that allows you to use variables to select an object property, or if there is another method to achieve the same functionality. Here is the code snippet for reference ...

Why does mapping only give me the last item when I try to map onto an object?

Why does mapping onto an object only give me the last item? Below is the object displayed in the console: 0: {Transport: 2} 1: {Implementation: 9} 2: {Management: 3} When I use ngFor, it only provides the last item const obj = this.assigned_group; // r ...

An error in typescript involving a "const" assertion and a string array

Currently, I am diving into the world of Typescript along with React. However, an error has emerged in my path that I can't seem to figure out. It's puzzling why this issue is occurring in the first place. Allow me to elaborate below. const color ...

What is the recommended approach for storing and retrieving images in the Angular 5 framework?

I have an Angular 5 app that utilizes Java rest services. The Java application stores images in a folder located outside of the Java app itself. Now, my goal is for the Angular app to be able to read these images. Although it makes sense to store them outs ...

Retrieve specific data points within a dataset

Within the dataset provided, I am attempting to retrieve specific values. { "id": "0f0126f5-aed3-49bb-97dd-7ad2d00b67a4", "retirementData": "{\"benefits\":[{\"availableBenefitOptions\":{\"anniversaryDate\":\"202 ...

A Promise is automatically returned by async functions

async saveUserToDatabase(userData: IUser): Promise<User | null> { const { username, role, password, email } = userData; const newUser = new User(); newUser.username = username; newUser.role = role; newUser.pass ...

When working with Angular 2 and Typescript, a common error message that may be encountered is "TypeError

Currently diving into Angular 2 and encountered a stumbling block while attempting to create a service. Despite my efforts in finding a solution, I seem to be missing something crucial. Error: A problem arises in angular2-polyfills.js:1243 with the error ...

TS type defined by JS constants

I am currently working on a project that involves both JavaScript and TypeScript. I am trying to find a solution to reduce code duplication when using JavaScript string constants by converting them into TypeScript types. For example, let's say I have ...

Unable to fake a fetch request using the 'fetch-mock-jest 1.5.1' library

I am attempting to simulate a fetch call using thefetch-mock-jest library, but the code continues to try accessing the remote address and ultimately fails with the error message FetchError: request to https://some.domain.io/app-config.yaml failed, reason: ...

Exploring Angular 6 with Universal Karma for effective module testing

Issue I have been facing challenges while testing my Angular 6 application with Karma. I am encountering errors such as: Can't bind to 'ngModel' since it isn't a known property of 'mat-select'. Although the import works in ...

Leveraging Renderer in Angular 4

Understanding the importance of using a renderer instead of directly manipulating the DOM in Angular2 projects, I have gone through multiple uninstallations, cache clearings, and re-installations of Node, Typescript, and Angular-CLI. Despite these efforts, ...

Having trouble with gsap.reverse() not functioning properly when using onMouseLeave event in React

I've been incorporating simple gsap animations into my React application. I have successfully triggered an animation.play() function on onMouseEnter, but for some reason, the animation.reverse() function is not functioning as expected. Here's ho ...

Error: FaConfig is not provided in the NullInjector

After incorporating angular-fontawesome into my angular application using npm as instructed on GitHub, everything seemed to work smoothly during development. However, I encountered an error when trying to build for production. The initial error message I ...