27

The following AngularJS application is working with ng-repeat and an applied filter. A certain applied filter leaves no values left. How can I display a notification?

js fiddle

HTML

<div >
<div data-ng-controller="myCtrl">


    <ul >
        <li data-ng-repeat="item in values | filter:filterIds()"> 
            <code>#{{item.id}}</code> Item
        </li>
    </ul>

    <p ng-show="!values.length">no vals with this filter</p>
    <button ng-click="loadNewFilter()"> filter now</button>
</div>


</div>

AngularJS

var app = angular.module('m', []);

app.controller('myCtrl', function ($scope) {
$scope.values = [{
    id: 1
}, ....
}];

$scope.filter = [1,2,3,4,5,6];

$scope.filterIds = function (ids) {
        return function (item) {
            var filter = $scope.filter;

                 return filter.indexOf(item.id) !== -1;         
        }
 }

$scope.loadNewFilter = function (){
    $scope.filter = [-1];
    $scope.$apply();
}

});
user1477955
  • 1,652
  • 8
  • 23
  • 35

7 Answers7

40

I think this is what you want:

var app = angular.module('myApp', []);    
app.controller('myCtrl', function ($scope) {
  $scope.values = [
    {id: 1}, 
    {id: 2}, 
    {id: 3}, 
    {id: 4}, 
    {id: 5}, 
    {id: 6}];
    
  $scope.filter = [1,2,3,4,5,6];
        
  $scope.filterIds = function (ids) {
    return function (item) {
      var filter = $scope.filter; 
      return filter.indexOf(item.id) !== -1;        
    }
  }
        
  $scope.loadNewFilter = function (){
    $scope.filter = [1,5];    
  }                 
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myApp">
  <div data-ng-controller="myCtrl">               
    <ul>
      <li data-ng-repeat="item in testValue=(values | filter:filterIds())"> 
        <code>#{{item.id}}</code> Item
      </li>
    </ul>           
    <p ng-show="!testValue.length">no vals with this filter</p>
    <button ng-click="loadNewFilter()"> filter now</button>
  </div>
</div>

FIDDLE LINK

This is Another one FIDDLE LINK check this also

Rajamohan Anguchamy
  • 1,726
  • 1
  • 17
  • 35
  • I would update that code, to show two messages, one if no 'values' initially exist

    no values exist

    , another if values exist, but all are filtered out

    no vals with this filter

    – Dmitri Algazin Feb 13 '15 at 11:15
  • @DmitriAlgazin Check this Updated ***FIDDLE LINK*** http://jsfiddle.net/RajamohanShilpa/z9daLbLm/13/ – Rajamohan Anguchamy Mar 10 '15 at 09:31
29

I would go with very simple CSS approach:

HTML:

<ul>
    <li data-ng-repeat="item in values | filter:filterIds()"> <code>#{{item.id}}</code> Item</li>
    <li class="no-items">There are no matching items.</li>
</ul>

CSS:

li + .no-items {
    display: none;
}

So basically li.no-items is only visible if there are no other LI's and hidden otherwise. I think this is better for performance than introducing one more watcher with ngShow/ngHide.

Demo: http://jsfiddle.net/z9daLbLm/5/

dfsq
  • 191,768
  • 25
  • 236
  • 258
  • You can add `.loading{display:none}` to prevent showing the message while loading – Ouadie Mar 29 '15 at 01:03
  • 1
    I like this best if there are multiple filters being done, its a true look at the DOM state without actually needing to investigate with overhead. – ericjam Feb 29 '16 at 05:27
8

Here's working example: http://jsfiddle.net/z9daLbLm/2/

You can save the result of the filter in ng-repeat

<div ng-repeat="item in filteredValues = (values | filter:filterIds())">{{item}}</div>

The result is stored in filteredValues Then use this filtered values in the DOM

<div ng-show="!filteredValues.length">No Items</div>
Vamsi
  • 9,510
  • 6
  • 38
  • 46
2

Please see here http://jsfiddle.net/ntofav3c/

change this:

<p ng-show="!values.length">no vals with this filter</p>

to:

 <p ng-hide="values | filter:filterIds()">no vals with this filter</p>
sylwester
  • 16,498
  • 1
  • 25
  • 33
  • I like this approach the best as its much more meaningful in the Angular sense but unfortunately gets cluttered when you have multiple filters upon the ng-repeat list. – ericjam Feb 29 '16 at 05:26
2

See this working jsfiddle: http://jsfiddle.net/z9daLbLm/4/ I added this code before your <ul> list

<div ng-if="(values|filter:filterIds()).length == 0">
    List is empty
</div>

It just shows "List is empty" text when your filtered values length is zero.

For more information refer to this link: How to display length of filtered ng-repeat data

Community
  • 1
  • 1
Glogo
  • 2,694
  • 2
  • 23
  • 23
0

You can use ng-switch to do this.

For example:

`    <div ng-app ng-controller="friendsCtrl">
    <label>Search: </label><input ng-model="searchText" type="text">
    <div ng-init="filtered = (friends | filter:searchText)">
    <h3>'Found '{{(friends | filter:searchText).length}} friends</h3>
    <div ng-switch="(friends | filter:searchText).length">
      <span class="ng-empty" ng-switch-when="0">No friends</span>
      <table ng-switch-default>
        <thead>
          <tr>
            <th>Name</th>
            <th>Phone</th>
          </tr>
        </thead>
        <tbody>
          <tr ng-repeat="friend in friends | filter:searchText">
            <td>{{friend.name}}</td>
            <td>{{friend.phone}}</td>
          </tr>
        </tbody>
      </table>
     </div>`
Aman Kumar
  • 4,533
  • 3
  • 18
  • 40
0

I recently faced the same kind of problems.. I had three filters and one orderBy in the ng-repeat and wanted to show some emptyList Messages....
The above solutions didnot work..so I made one out of my own.

  • Made the emptymsg as background div and the mainContainer as top div..
  • The emptyMsg div will always be shown, so whenever there is no value in list.. the emptyMsg will be the only div showing. PS: the code snippet wont run..because the additional libraries are not added.. This is just to give you an idea!
    //empty msg....
    .emptyMsg{
        position: absolute;
        left: 0;right: 0;
        margin: auto;
        color: gray;
        text-align: center;
        font-size:3.0em;
        z-index: 0;
    }
    .activityItem {
        margin: 0px !important;
        padding: 0px !important;
        border: 0px !important;
    }
    .mainContainer {
        z-index: 999;
        width: 100%;
        height: 40px;
        left: 0px;
        margin-top: 10px;
        display: inline-block;
    }
    <h4>List of Activities</h4>
            <ion-list>
               <div class="emptyMsg">No Activities found!</div>
                <div class="item activityItem" ng-repeat="activity in activities | orderBy:field1Order:order.reverse1 | filter:importanceFilter | filter:motiveFilter track by $index">
                       <div class="mainContainer">
    
                                <div class="divBar">{{activity.energy}}%</div>
                       
                    </div>
                </div>
                
            </ion-list>
Sijan Gurung
  • 727
  • 5
  • 12