2

I want to display a list of items in a table and allow users to filter the items using form controls.

My Problem
I am able to accomplish this when the controller first executes, but when I change the values of the inputs, the table doesn't re-render with the correct data.

My Question
How can I make my table filter based on new values in the form fields?

Live Example
http://plnkr.co/edit/7uLUzXbuGis42eoWJ006?p=preview

Javascript

var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope) {
    $scope.travelerFilter = 2;
    $scope.groupFilter = "A";

    $scope.records = [
        { leadName: "Jesse", travelerCount: 1, group: "A"},
        { leadName: "John", travelerCount: 1, group: "B"},
        { leadName: "James", travelerCount: 2, group: "A"},
        { leadName: "Bill", travelerCount: 2, group: "B"}
    ];

    var travelerCountFilter = function(record) {
        return record.travelerCount >= $scope.travelerFilter;
    };

    var groupFilter = function(record) {
        return record.group === $scope.groupFilter;
    };

    $scope.filteredRecords = _.chain($scope.records)
        .filter(travelerCountFilter)
        .filter(groupFilter)
        .value();
});

Html

<!doctype html>
<html ng-app="plunker" >
<head>
  <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.5/angular.js"></script>
  <script src="//cdnjs.cloudflare.com/ajax/libs/underscore.js/1.4.4/underscore-min.js"></script>
  <script src="app.js"></script>
</head>
<body ng-controller="MainCtrl">

  <p>Show records with at least <input type="number" ng-model="travelerFilter" /> travelers.</p>
  <p>Group <input type="text" ng-model="groupFilter" /></p>

  <table>
      <tr>
        <th>Name</th>
        <th>Count</th>
        <th>Group</th>
      </tr>
      <tr ng-repeat="record in filteredRecords">
          <td>{{record.leadName}}</td>
          <td>{{record.travelerCount}}</td>
          <td>{{record.group}}</td>
      </tr>
  </table>
</body>
</html>
jessegavin
  • 74,067
  • 28
  • 136
  • 164

2 Answers2

3

You can specify the filter as part of the ng-repeat, i.e.:

<tr ng-repeat="record in records | filter:{group:groupFilter} | filter:{travelerCount:travelerFilter}">

See here for a live version: http://plnkr.co/edit/1UcGDpwUAbtvEhUyCFss?p=preview

Chris Montgomery
  • 2,344
  • 2
  • 19
  • 30
  • Thanks Chris. I can definitely solve the problem at hand this way. I _was_ really hoping to be able to create something like a KnockoutJS computed property in Angular rather than creating several filters. I will keep hunting. – jessegavin Apr 08 '13 at 19:22
3

angular can automatically two-way-bind everything for you without the need for filters:

JS:

$scope.filteredRecords = function() {
  return $scope.records.filter(function(record, i) {
    return record.travelerCount === $scope.travelerFilter &&
      record.group === $scope.groupFilter;
  });
}

HTML:

<tr ng-repeat="record in filteredRecords()">

See here for a live example: http://plnkr.co/edit/aeBv2soGG06Trpp9WI4f?p=preview

Chris Montgomery
  • 2,344
  • 2
  • 19
  • 30