Question

I want to filter ng-repeat so that it only shows rows where all key/value pairs are present.

HTML

<div ng-app="myApp" ng-controller="oneController">
<table class="table table-bordered table-hover">
  <thead>
    <tr>
      <th>Country</th>
      <th>1960</th>
      <th>1970</th>
    </tr>
    <tbody>
      <tr ng-repeat="country in countries | orderBy: country.name">
        <td>{{country.name}}</td>
        <td>{{country.1960 | number}}</td>
        <td>{{country.1970 | number}}</td>
      </tr>
    </tbody>
</table>

Javascript

angular.module('myApp', []).
controller('oneController', function($scope) {
  $scope.countries = [
      {"name":"Aruba", "1960":"1567"},
     {"name":"Andorra","1960":77865,"1970":78360},
  ];
});

So, in this example, I do not want Aruba displayed, only Andorra.

Full example @ CSSDeck: http://cssdeck.com/labs/1aksiuuu (I do not want Aruba displayed)

Was it helpful?

Solution

Expanding on the custom filter concept, I think the point is that you don't know which property may be missing for any given object. By looping through all the properties in all the objects, you can create a master list of every property that exists on at least one object:

$scope.properties = function(){
  var props = [];    
  angular.forEach($scope.countries, function(country){
    for(var prop in country){
      if(props.indexOf(prop) == -1)
        props.push(prop);
    }
  });
  return props;
};

Now you can make a filter function that checks against this list:

$scope.hasAllProperties = function(item){
  var found = true;
  angular.forEach($scope.properties(), function(prop){
    if(item[prop] == undefined){
      found = false;
      return;
    }
  });
  return found;
}

HTML:

<tr ng-repeat="country in countries | filter: hasAllProperties | orderBy: country.name">

You might want to cache the master list of properties to cut down on the number of times $scope.properties() gets called.

Demo (I've also removed a property from Argentina in this demo)

OTHER TIPS

Can always make a custom filter:

<tr ng-repeat="country in countries | filter:allProperties | orderBy: country.name">

And the filter

$scope.allProperties = function(item) {
    return item.name && item.1960 && item.1970
}

One solution is to use the filter filter:

<tr ng-repeat="country in countries | filter:{name: '', 1960: '', 1970: ''} | orderBy:'name'">

Create a filter inside your controller like below:

 $scope.search = function (item){
    return item.hasOwnProperty("1970");
  };

use the filter like below:

<tr ng-repeat="country in countries | filter:search | orderBy: country.name">

Forked a new URL from yours: http://cssdeck.com/labs/kggmrzow

Try this:

<tr ng-repeat="country in countries | orderBy: country.name">
  <label ng-show="country.1960!=undefined && country.1970!=undefined">
    <td>{{country.name}}</td>
    <td>{{country.1960 | number}}</td>
    <td>{{country.1970 | number}}</td>
  </label>
</tr>
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top