Ray
Ray

Reputation: 1145

Angularjs ng-repeat with filter scope object

I have a requirement to filter rows in ng-repeat based on whats in $scope.filterObject. I have a data in $scope.customerData that contains all the customer information, but when looping through each customer, I would only like to show results based on whats in $scope.filterObject. For example, only show rows of customers that have jobs that are in $scope.filterObject.

Here is the JSFiddle link.

Here is what I have so far:

HTML:

<table ng-app="app" ng-controller="AppsCtrl">
  <thead>
    <tr>
      <th>+</th>
      <th>Name</th>
      <th>Email</th>
      <th>DOB</th>
      <th>Hobby</th>
    </tr>
  </thead>
  <tbody ng-repeat="customer in customerData">
    <tr>
      <td><a href="#" class="main" ng-click="expandTable($event)">+</a></td>
      <td>{{customer.name}}</td>
      <td>{{customer.email}}</td>
      <td>{{customer.DOB}}</td>
      <td>{{customer.Hobby}}</td>
    </tr>
    <tr class="showhide">
      <td> </td>
      <td>Degree</td>
      <td>{{customer.Degree}}</td>
      <td>Job title</td>
      <td>{{customer.Job}}</td>
    </tr>
    <tr class="showhide">
      <td></td>
      <td>Country</td>
      <td>{{customer.Country}}</td>
      <td>City</td>
      <td>{{customer.City}}</td>
    </tr>
  </tbody>
</table>

JS:

// AngularJS toggle table

var app = angular.module('app', []);
app.controller('AppsCtrl', function($scope) {
  $scope.expandTable = function() {
    console.log($(event.target).closest('tr').nextUntil("tr.main"));
    $(event.target).closest('tr').nextUntil("tr.main").slideToggle();
    // console.log($(event.currentTarget).parent().parent());
  }
  var data = [{
    "name": "John",
    "email": "[email protected]",
    "DOB": "01/05/1968",
    "Degree": " BSC",
    "Job": "Engineer",
    "Hobby": "Football",
    "Country": "US",
    "City": "Houston"
  }, {
    "name": "Jessica",
    "email": "[email protected]",
    "DOB": "03/05/1976",
    "Degree": " Accounting",
    "Job": "CPA",
    "Hobby": "Video games",
    "Country": "US",
    "City": "Fredericks"
  }, {
    "name": "Andrew",
    "email": "[email protected]",
    "DOB": "06/12/1998",
    "Degree": " PHD",
    "Job": "Professor",
    "Hobby": "Writing",
    "Country": "US",
    "City": "San Diago"
  }, {
    "name": "Rich",
    "email": "[email protected]",
    "DOB": "09/21/1988",
    "Degree": " PHD",
    "Job": "Technician",
    "Hobby": "Writing",
    "Country": "US",
    "City": "San Diago"
  }];
  $scope.customerData = data;
  $scope.filterObject = [{
    "Job": "CPA"
  }, {
    "Job": "Engineer"
  }]
});

\ Any suggestion and help is really appreciated. :)

Upvotes: 0

Views: 291

Answers (2)

Nandor Persanyi
Nandor Persanyi

Reputation: 36

$scope.customerData = data.filter(function(user){
    var found = false; 
    $scope.filterObject.forEach(function(filter){
    	if(filter.Job === user.Job)
      	found = true;
    })
    return found;
});

Fiddle: https://jsfiddle.net/nandorpersanyi/yLsxqkx8/

Regarding Nedev's answer: DOM filters can have an impact on performance, presuming we are handling large datasets (eg $scope.customerData has thousands of customers). In this case you are better off filtering within the controller, unless you need user interaction with the filter. And if your filter object updates dynamically, just $watch it for changes, then rerender customerData when changed

Upvotes: 1

Nedev
Nedev

Reputation: 446

You can use angular filter function in ng-repeat to compare customerArray with customerObject and then return only element that match customerObject properties.

//Instead of array    
$scope.filterObject = {
    "Job": "CPA"
  };

HTML :

  <tr ng-repeat="customer in customerData | filter: filterObject">

Otherwise you can create a custom filter function to compare field or array of fields :

 app.filter('customerFilter', function() {
  return function( items, filterParams) {
    var filtered = [];
    angular.forEach(items, function(item) {
      if(filterParams.Job.indexOf(item.Job) !== -1) {
        filtered.push(item);
      }
    });
    return filtered;

}; });

HTML :

   <tr ng-repeat="customer in customerData | customerFilter: filters">

Customer controller:

$scope.filters = {
  "Job" :["Technician","CPA"]
  }

working example here : https://jsfiddle.net/Nedev_so/wb1hqeca/

Upvotes: 2

Related Questions