简体   繁体   中英

ngFor creates unwanted copies of ng-template

I have an issue with ngFor directive, and I just can't find a way around it:

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

So, if the image is "profile image", use it. If not, use the template with the placeholder image. In some cases, if there are more images in the array and none of them is a profile image, it shows the ng-template but duplicated many times (by number of images in the array)..., but it should show it only once and "break out" of the loop.

Am I missing something very obvious?

There is no way to break out of an ngFor loop. However, there is a way to solve your problem.

You can create a method in your component that will loop over the array and check if there's a profile image there, then you can alter your HTML and you check wether the array contains a profile image or not. If not, then you can just show the ngTemplate.

Example


<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;
}

EDIT: Alternative solution

As Chris G said as a response. You can also filter your images by the images that have profile images. This way you can check whether there is atleast one image in the filtered array. If not, show 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;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM