Using ngFor results in duplicate instances of ng-template

I'm facing a challenge with the ngFor directive and I'm struggling to find a solution:

<ng-container *ngIf="user.images.length > 0">
   <div *ngFor="let image of images">
        <img
           *ngIf="image.isProfileImage; else noImage"
           [src]="image.path"
        />
   </div>
</ng-container>
                    
<ng-template #noImage>
   <img src="https://someplaceholder.com"/>
</ng-template>

Basically, I only want to display the profile image if it exists. If not, I want to show a placeholder image using a template. However, I noticed that in some instances when there are multiple non-profile images in the array, the template gets duplicated for each one instead of appearing just once. It seems like I am missing something obvious here. Any ideas?

Answer №1

If you find yourself stuck in an ngFor loop, don't worry - there's always a solution waiting for you.

A handy method you can use is to create a function within your component that iterates through the array to check for profile images. Once you've identified them, you can tweak your HTML code accordingly by determining whether the array contains any profile images. If not, you can opt to display the ngTemplate instead.

Take a look at an example below:


<ng-container *ngIf="user.images.length">
<ng-container *ngIf="containsProfileImage(); else noImage">
   <div *ngFor="let image of images">
        <img
           *ngIf="image.isProfileImage"
           [src]="image.path"
        />
   </div>
</ng-container>
</ng-container>

<ng-template #noImage>
   <img src="https://someplaceholder.com"/>
</ng-template>


containsProfileImage(): boolean{
   let returnVal = false;
   
   this.user.images.forEach(image => {
      if (image.isProfileImage) {
         returnVal = true;
         return;
      }
   }

   return returnVal;
}

UPDATE: An Alternative Approach

In response to Chris G's suggestion, another way to tackle the issue is by filtering out images with profile images and checking the length of the filtered array. This will help you determine if there's at least one image in the list. If not, simply display the noImage ngTemplate.

<ng-container *ngIf="user.images.length">
<ng-container *ngIf="filteredImagesLength; else noImage">
   <div *ngFor="let image of images">
        <img
           *ngIf="image.isProfileImage"
           [src]="image.path"
        />
   </div>
</ng-container>
</ng-container>

<ng-template #noImage>
   <img src="https://someplaceholder.com"/>
</ng-template>
get filteredImagesLength(): number {
   return user.images.filter(i => i.isProfileImage)?.length;
}

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

Passing "this" to the context provider value in React

While experimenting with the useContext in a class component, I decided to create a basic React (Next.js) application. The app consists of a single button that invokes a function in the context to update the state and trigger a re-render of the home compon ...

Passing an array from the PHP View to a JavaScript function and plotting it

Greetings, I am currently facing the following tasks: Retrieving data from a database and saving it to an array (CHECK) Sending the array from Controller to View (CHECK) Passing that array to a JavaScript function using json_encode (CHECK) Plotting the ...

Unable to locate any static exports within the TypeScript library bundle

In my file Style.ts, I have a class called Style: export class Style { ... } The Style class consists of properties, methods, and a constructor, along with import statements for other class dependencies. It is being used by other classes through the ...

What is the process of incorporating HTML into a jQuery program in order to immerse the world in an element?

I am looking to utilize HTML with the value in a checkbox, After adding a shortcode: <label class="HCheck">(this is val 1 )</label> and incorporating jQuery to change it to: <label class="HCheck">(this is val 1 ) ...

Leveraging Material-UI in Electron Environment

I'm currently working on an electron app using React and incorporating Material-UI for the user interface. I've added a datepicker and timepicker to a component, but when clicking on the input in the electron app, nothing happens. I'm unsure ...

Managing JSON data through AJAX in ColdFusion

For my external API call using AJAX, I am incorporating a local API setup as an intermediate step. The process is as follows: The Ajax call sends data to localAPI.cfm. Within localAPI.cfm, there is a <cfhttp> tag to forward the data to an external ...

JavaScript for switching between grid layouts

I have organized 3 DIVs using a grid layout. There is a Navigation bar with an on-click event attached to it. When a button on the nav-bar is clicked, I want the JavaScript function to display the corresponding grid associated with that button. Currently, ...

Issue with IE11: the selected list is not displayed when using the <s:optiontransferselect> tag

When moving groups from left to right in the s:optiontransferselect for selectedGrps and unselectedGrps, the SelectedGroups list is showing as null on form submission in IE11. However, in Chrome and Mozilla, it functions correctly. Any advice would be grea ...

jQuery - class remains unchanged on second click event

Operations: Upon clicking on an element with the class thumb_like or thumb_unlike, a like will be added or removed for the image using a POST request. The element with the class thumb_count will increase or decrease based on user actions. For example, lik ...

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 ...

Attempting to locate an element within the DOM using TypeScript

I am completely new to TypeScript. I have been attempting to locate an element using a selector, but no matter what I tried, the findElement() method always returns undefined. Can someone please point out where my mistake might be? Any assistance would b ...

Determining the selected input from numerous checkboxes in a React code and saving them within a blank array

I am currently working on a React project where I have multiple checkboxes that interact with a single component. The data in this component is supposed to change based on the checkbox that is selected. However, I am struggling to keep track of which check ...

NextJS API routes consistently provide a status code of 200 upon execution

I am new to the concepts of Next.js, and I recently encountered an issue while attempting to fetch data from an API. The API is designed to check if a user session exists (i.e., if the user is logged in) and then returns a JSON response through a GET reque ...

What is the best way to structure a data object in Javascript or VueJs?

As I work on developing a small application using VueJs, the data I receive is structured in a particular format: { "interactions":[ { "id":14, "user_id":1, "schedule":"2017-06-04 05:02:12", "typ ...

What exactly does the term "library" refer to in the context of jQuery, a JavaScript

I'm confused about the concept of a library - when it comes to jQuery, can it be described as a large file containing multiple plugins that are pre-made and ready for use? ...

Facing a dilemma: Javascript not updating HTML image source

I am facing an issue while attempting to modify the source of my HTML image element. Despite using document.getElementId('image') in my code, I am unable to make it work as intended. Surprisingly, there are no errors displayed. Interestingly, whe ...

Utilize interface as a field type within a mongoose Schema

I am currently working with typescript and mongoose. I have defined an interface like this: interface Task { taskid: Boolean; description: Boolean; } My goal is to create a schema where one of the fields contains an array of Tasks: const employeeSche ...

The time zones between Node 8 and Node 11 are not the same

Executing a basic new Date().toString() command produces different results on Node 11 compared to Node 8. In Node 11, the output includes the full timezone abbreviation like this: 'Fri May 10 2019 10:44:44 GMT-0700 (Pacific Daylight Time)' On t ...

Error message 2339 - The property 'toggleExpand' is not recognized on the specified type 'AccHeaderContextProps | undefined'

When utilizing the context to share data, I am encountering a type error in TypeScript stating Property 'toggleExpand' does not exist on type 'AccHeaderContextProps | undefined'.ts(2339). However, all the props have been declared. inter ...

Deviations in Scriptaculous Callbacks during Movement Effects

I am looking to create a dynamic menu item that moves out 5px on mouseover and returns to its original position using Scriptaculous. I have implemented the afterFinish callback to ensure that the bump-out effect is completed before the item moves back in. ...