Filter by multiple columns with ng-repeat

Solution 1:

It's not hard to create a custom filter which allows you to have as many arguments as you want. Below is an example of a filter with one and two arguments, but you can add as many as you need.

Example JS:

var app = angular.module('myApp',[]);
app.filter('myTableFilter', function(){
  // Just add arguments to your HTML separated by :
  // And add them as parameters here, for example:
  // return function(dataArray, searchTerm, argumentTwo, argumentThree) {
  return function(dataArray, searchTerm) {
      // If no array is given, exit.
      if (!dataArray) {
          return;
      }
      // If no search term exists, return the array unfiltered.
      else if (!searchTerm) {
          return dataArray;
      }
      // Otherwise, continue.
      else {
           // Convert filter text to lower case.
           var term = searchTerm.toLowerCase();
           // Return the array and filter it by looking for any occurrences of the search term in each items id or name. 
           return dataArray.filter(function(item){
              var termInId = item.id.toLowerCase().indexOf(term) > -1;
              var termInName = item.name.toLowerCase().indexOf(term) > -1;
              return termInId || termInName;
           });
      } 
  }    
});

Then in your HTML:

<tr ng-repeat="item in data | myTableFilter:filterText">

Or if you want to use multiple arguments:

<tr ng-repeat="item in data | myTableFilter:filterText:argumentTwo:argumentThree">

Solution 2:

Use this to search on All Columns (can be slow): search.$ AngularJS API: filter

Any Column Search:
<input ng-model="search.$"> 
<table>
<tr ng-repeat="friendObj in friends | filter:search:strict">
...

Solution 3:

To expand on the excellent answer by @charlietfl, here's a custom filter that filters by one column(property) which is passed to the function dynamically instead of being hard-coded. This would allow you to use the filter in different tables.

var app=angular.module('myApp',[]);        
app.filter('filterByProperty', function () {
        /* array is first argument, each addiitonal argument is prefixed by a ":" in filter markup*/
        return function (dataArray, searchTerm, propertyName) {
            if (!dataArray) return;
            /* when term is cleared, return full array*/
            if (!searchTerm) {
                return dataArray
            } else {
                /* otherwise filter the array */
                var term = searchTerm.toLowerCase();
                return dataArray.filter(function (item) {
                    return item[propertyName].toLowerCase().indexOf(term) > -1;
                });
            }
        }
    });

Now on the mark-up side

<input type="text" ng-model="filterText" />

<table>
  <tr ng-repeat="item in data |filterByProperty:filterText:'name'"><td>{{ item.id }}</td><td>{{ item.name }}</td>...</tr>
</table>