Search code examples
angularngforangular-ng-if

How to skip iteration in *ngFor loop without drawing in the view an empty item when *ngIf returns false


Im trying to draw in a grid a set of items that meet a condition, but an iteration does not meet the condition, and empty grid item is still drawn in the view. How do I stop the *ngFor (or whatever is responsible) from drawing

<div class="grid main" *ngIf="blogPosts$ | async as blogPosts">
<div class="tile" *ngFor="let blogPost of blogPosts.items">
    <div *ngIf="blogPost.fields.category == this.catLink.getCat()">
        <div (click)="catLink.setCat(blogPost.fields.category)" 
           [routerLink]="['/article', blogPost.sys.id]" >
            <img width="375" height="250" [src]="blogPost.fields.featuredImage.fields.file.url" alt="">
            <div class="title"><span>{{ blogPost.fields.title }}</span></div>
        </div>
    </div>
</div>
</div>

Solution

  • Keeping in mind that the better solution would be to filter your data in code rather than in the template, this might help.

    I am guessing that the empty element is the div with a class of tile. It is always printed because you iterate on a div, which inserts an element in the DOM. You also print a div with the nested NgIf.

    Try using <ng-container> instead and print only if the condition is met.

    <div class="grid main" *ngIf="blogPosts$ | async as blogPosts">
    
        <ng-container *ngFor="let blogPost of blogPosts.items">
            <ng-container *ngIf="blogPost.fields.category == this.catLink.getCat()">
                <div class="tile">
                    <div>
                        <div (click)="catLink.setCat(blogPost.fields.category)" 
               [routerLink]="['/article', blogPost.sys.id]" >
                            <img width="375" height="250" [src]="blogPost.fields.featuredImage.fields.file.url" alt="">
                        <div class="title"><span>{{ blogPost.fields.title }}</span></div>
                    </div>
                </div>
            </ng-container>
        </ng-container>
    </div>