Momo Araki Momo Araki - 1 month ago 10
AngularJS Question

AngularJS filter list based on array properties

How to create the following filter using AngularJS?

Here's a visual diagram explaining the question. I've been trying to figure this out for a bit and would really appreciate some help.

I have a list of companies:

$scope.companies = [
{
id:"company_01",
ratings: [ 5, 5, 5, 5, 0, 5, 4, 4, 1, 3, 0, 0 ]
},
{
id:"company_02",
ratings: [ 5, 4, 5, 4, 0, 5, 4, 4, 1, 3, 0, 0 ]
}
...
];


where each
company
has a property called
ratings
—- an array of numeric values (1-5) that represent scores for a given set of
issues
:

$scope.issues = [
{
label:'Carbon Footprint',
selected: true,
value: 3
},

...

{
label:'Consumer Health',
selected: false,
value: null
},

...

{
label:'Employee Satisfaction',
selected: true,
value: 5
},

...
];


The indices of
$scope.companies[i].ratings
correspond to the indices of
$scope.issues
.

Each issue has:


  • a
    selected
    property, a boolean toggled by a UI checkbox

  • a
    value
    property, a number (1-5) adjusted by a UI slider



I'd like to filter
$scope.companies
based on whether
company.ratings[i] >= issue[i].value
for each selected
issue[i]
. If an
issue
is not selected, it shouldn't affect the filter.

A related question is what the best way to watch for changes on
$scope.issues
would be. e.g. when a user selects/deselects an issue or adjusts a slider.

Thanks very much!

Answer Source

The Filter

Here's a goodRatingsOnly filter that filters the $scope.companies array based on the contents of the $scope.issues array. With several loops, it searches for a reason to not return the record i.e. when a poor rating is found.

  app.filter("goodRatingsOnly", function thisFilter() {
    return function(companies, issues){
      return companies.filter(function(comp){
        var poorRatingFound = false;
        issues.forEach(function(issue, i){  
          if (issue.selected){
            if (!poorRatingFound){
              poorRatingFound = comp.ratings[i] < issue.value;
              console.log(poorRatingFound);
            }
          }
        });
        return !poorRatingFound;
      });
    }
  });

Sample Usage

In the controller:

$scope.filteredCompanies = $filter("goodRatingsOnly")($scope.companies, $scope.issues); 

Or on ng-repeat in the view:

ng-repeat="comp in companies | goodRatingsOnly: issues"

Demo

CodePen: Using an array to filter another array in a custom filter