OdeToCode IC Logo

Building Multiple Filters with Lo-Dash and AngularJS

Thursday, May 29, 2014

You can try the code in this post yourself.

Imagine we have the following movie data returned by an API call from the server.

var movies = [
    { title: "Godzilla", genre:"Action", released: 2014},
    { title: "Neighbors", genre: "Comedy", released: 2014},
    { title: "Into The Woods", genre: "Musical", released: 2014},
    . . .
];

Now, we need to display the data and allow the user to filter on genre, release year, or both. First, we’ll use lodash to build a unique list of available options for these attributes, and then store the options in scope.

app.controller("mainController", function($scope, movieData) {

    $scope.movies = movieData.getAll();

    $scope.genres = _.chain($scope.movies).pluck("genre").uniq().sortBy().value();
    $scope.years = _.chain($scope.movies).pluck("released").uniq().sortBy().value();

    $scope.clearFilters = function(){
        $scope.selectedGenre =  undefined;
        $scope.selectedYear = undefined;
    };

});

In the view we can build the filtering selects and a table using ngOptions and ngRepeat.

<div ng-controller="mainController">

  <select ng-model="selectedGenre" ng-options="genre for genre in genres"></select>
  <select ng-model="selectedYear" ng-options="year for year in years"></select>
  <button ng-click="clearFilters()">Clear</button>

  <table class="table">
    <thead>. . . </thead>
    <tbody>
      <tr ng-repeat="movie in movies |
            filter:{ genre: selectedGenre, released:selectedYear }">
        <td>{{movie.title}}</td>
        <td>{{movie.genre}}</td>
        <td>{{movie.released}}</td>
      </tr>
    </tbody>
  </table>

</div>

Notice how the filter filter in Angular understands how to take an object expression and apply predicates to the specified attributes.