I thought this would be a very common thing, but I couldn't find how to handle it in AngularJS. Let's say I have a list of events and want to output them with AngularJS, then that's pretty easy:

<ul>
    <li ng-repeat="event in events">{{event.title}}</li>
</ul>

But how do I handle the case when the list is empty? I want to have a message box in place where the list is with something like "No events" or similar. The only thing that would come close is the ng-switch with events.length (how do I check if empty when an object and not an array?), but is that really the only option I have?


Solution 1:

You can use ngShow.

<li ng-show="!events.length">No events</li>

See example.

Or you can use ngHide

<li ng-hide="events.length">No events</li>

See example.

For object you can test Object.keys.

Solution 2:

And if you want to use this with a filtered list here's a neat trick:

<ul>
    <li ng-repeat="item in filteredItems  = (items | filter:keyword)">
        ...
    </li>
</ul>
<div ng-hide="filteredItems.length">No items found</div>

Solution 3:

You might want to check out the angular-ui directive ui-if if you just want to remove the ul from the DOM when the list is empty:

<ul ui-if="!!events.length">
    <li ng-repeat="event in events">{{event.title}}</li>
</ul>

Solution 4:

With the newer versions of angularjs the correct answer to this question is to use ng-if:

<ul>
  <li ng-if="list.length === 0">( No items in this list yet! )</li>
  <li ng-repeat="item in list">{{ item }}</li>
</ul>

This solution will not flicker when the list is about to download either because the list has to be defined and with a length of 0 for the message to display.

Here is a plunker to show it in use: http://plnkr.co/edit/in7ha1wTlpuVgamiOblS?p=preview

Tip: You can also show a loading text or spinner:

  <li ng-if="!list">( Loading... )</li>

Solution 5:

<ul>
    <li ng-repeat="item in items | filter:keyword as filteredItems">
        ...
    </li>
    <li ng-if="filteredItems.length===0">
        No items found
    </li>
</ul>

This is similar to @Konrad 'ktoso' Malawski but slightly easier to remember.

Tested with Angular 1.4