Issue
I am trying to show a series of material cards based on a flag in my data. If the flag is falsy, I'm still getting an empty div (and thus extra space) injected into the DOM.
Assume I have an array of Fruit
objects that have an isBanana
flag. My template looks like:
<div *ngIf="fruit$ | async as fruits">
<!-- NOT bananas -->
<div *ngFor="let fruit of fruits">
<mat-card *ngIf="!fruit.isBanana" [fruit]="fruit"></mat-card>
</div>
<!-- Bananas -->
<div *ngFor="let fruit of fruits">
<mat-card *ngIf="fruit.isBanana" [fruit]="fruit"></mat-card>
</div>
</div>
I realize it's not ideal to loop through the array twice, but due headers/sections in my actual application, that's just kinda the way it has to be.
Anyhoo, the final render in the browser is such that, in the first/non-banana section, I successfully get cards without bananas, but each time that for loop comes across a fruit object that's not a banana, it injects an empty div, which adds space between cards where there should not be, such as
<div class="ng-star-inserted">
<div>
<mat-card><!-- card template --></mat-card>
</div>
<div><!-- literally just an empty div --></div>
</div>
I would think that if the condition is false, nothing would be rendered, but clearly that's not the case.
Solution
You have the conditional on the <mat-card>
, so only this element gets removed. To remove the wrapping <div>
you need to put the *ngIf
on the <div>
element. Since you cannot have two structural directives on one element, you will have to wrap the <div>
with <ng-container>
and move the *ngFor
there. <ng-container>
won't be added to the DOM, so you'll end up with the same structure as you would without it.
<div *ngIf="fruit$ | async as fruits">
<!-- NOT bananas -->
<ng-container *ngFor="let fruit of fruits">
<div *ngIf="!fruit.isBanana">
<mat-card [fruit]="fruit"></mat-card>
</div>
</ng-container>
<!-- Bananas -->
<ng-container *ngFor="let fruit of fruits">
<div *ngIf="fruit.isBanana">
<mat-card [fruit]="fruit"></mat-card>
</div>
</ng-container>
</div>
Answered By - Helios