Niranjan Shankar
Niranjan Shankar

Reputation: 147

How to find if my *ngFor returns empty?

I have the following code:

<ng-container *ngFor="let art of artefacts; let i = index">
  <div *ngIf="art.isSelected == true" fxLayout="row" class="selected-artefacts">
  </div>
</ng-container>

I find all items in artefacts and display if they have a property isSelected == true. Now if there is no element in artefacts that has isSelected = true, I need to display "No items to display". How do I achieve this?

Upvotes: 10

Views: 28471

Answers (5)

G&#252;nter Z&#246;chbauer
G&#252;nter Z&#246;chbauer

Reputation: 657058

If you use a pipe to filter (for example | filter) then you can use it like:

<div *ngFor="let item of artefacts">{{item.name}} 
  <input type="checkbox" [(ngModel)]="item.isSelected" (ngModelChange)="tick = tick+1">
</div>

<hr>

<ng-container *ngIf="artefacts | isSelected:tick as result; else noItems">
<!-- else is to cover the case where "artefacts" is "null" or "undefined" -->

    <div *ngFor="let item of result; let i = index" fxLayout="row" 
        class="selected-artefacts">{{item.name}}</div>

    <!-- the case where the pipe returns an empty array  -->
    <ng-container *ngIf="!result.length" [ngTemplateOutlet]="noItems"></ng-container>
</ng-container>

<ng-template #noItems>no Items</ng-template>

StackBlitz example

as was added in https://github.com/angular/angular/blob/master/CHANGELOG.md#400-rc4-2017-03-17

Upvotes: 18

Caco
Caco

Reputation: 131

An alternative way to avoid IF/ELSE for this scenario uses CSS only, and it works in any framework (Angular, React, Vue, ...)

.no-item:not(:first-child) {
display:none;
}

Simply wrap the list with any tag (section, div, ul, ...) and add a last item with the message you want to display and add the class above.

Find a working example here: https://codepen.io/cacothi/pen/vYEJxKR

Upvotes: 9

user4676340
user4676340

Reputation:

<ng-container *ngFor="let art of artefacts; let i = index">
  <div *ngIf="art.isSelected" fxLayout="row" class="selected-artefacts">
    <!-- Content -->
  </div>
</ng-container>
<ng-container *ngIf="noneSelected">
  <!-- none selected -->
</ng-container>

In your controller

this.noneSelected = this.artefacts.filter(a => a.isSelected).length;

Upvotes: 1

user6781560
user6781560

Reputation:

Doing this on my phone so text only answer.

The way to do this is to check if your array length is 0. If so then bound a css property to text that says the message you want to say.

Easy

Upvotes: -3

Suraj Rao
Suraj Rao

Reputation: 29614

You can simply have an *ngIf condition after the loop.

<ng-container *ngFor="let art of artefacts; let i = index">
  <div *ngIf="art.isSelected == true" fxLayout="row" class="selected-artefacts">
  </div>
</ng-container>
<!-- here -->
<div *ngIf="!artefacts || hasNoSelectedArtefacts()">
   No items to display
</div>

Have a function in your component side which checks the array:

hasNoSelectedArtefacts(){
  return artefacts.filter(art => art.isSelected).length===0;
}

Array.prototype.filter can be used to check if there are any items with isSelected.

Upvotes: 5

Related Questions