AngularJS过滤记录中字段(数组)中相应值的记录

So I am a newbie on AngularJS and I've been trying to get some sort of answer for this but no luck, hence this post.

I have an array of objects (JSON), and in a single object, there is a field called categories, this field is actually an array itself and can hold multiple values.

The filter that I'm looking for is, there is a "select" and user will pick a "select" value and all the records having that value in their categories array should appear to the user and rest can be hidden. This "select" has multiple selection but I'm considering to keep it to single selection. But since I want to deliver the best product, I would really appreciate if you can help me out for both multiple and single select.

Here is the sample data:

var jobs = [{"ID":"10","Title":"SQA Engineer","Employer":"XXXX","Address":"XXX Floor","Email":"XXXX","ContactNumber":"","Description":"1 year experience.","Qualification":"XXXX","LastApplyDate":"2016-08-26","Type":"1","CreatedDT":"2016-08-06 13:06:36","CreatedBy":null,"Categories":["25","28"]},{"ID":"8","Title":"Maid","Employer":"XXX","Address":"XXX","Email":"XXXX","ContactNumber":"XXXX","Description":"","Qualification":"NONE","LastApplyDate":"2016-08-26","Type":"1","CreatedDT":"2016-08-06 12:27:17","CreatedBy":null,"Categories":["28"]}];

Okay, so there are two different approaches here. One is very simple, just using the basic, built-in angularjs filter api, and the other is done by creating our own custom filter.

First (easy) approach

Single value selector for job categories, returns all jobs that contain a match for the selected category.

Edit - Updated code & demo based on comments! Working DEMO

<label>Category: 
    <select ng-model="category" ng-options="category.id as category.name for category in categories"></select>
</label>
<div class="results">
    <div class="job-listing" 
         ng-bind="job | json"
         ng-repeat="job in jobs | filter:{Categories: category}:true">
    </div>
</div>


Second (more advanced) approach

Multiple value selector for job categories, returns all jobs that contain a match for ALL selected categories. (i.e. a job with categories ["25"] will return false if "25" and "26" are selected)

Working DEMO

Here we have to create a custom filter, because, although angular's built-in filter does a lot of great stuff, it has its limitations.

Our custom filter (match ALL search terms)

app.filter("getMatches", function () {
  return function (items, options) {
    var options = options || {};
    var searchField = options.searchField || "";
    var searchTerms = options.searchTerms || [];
    if (searchField === "" || !searchTerms.length || (searchTerms.length === 1 && searchTerms[0] === '')) {
      return items;
    }
    return items.filter(function (item) {
      return !searchTerms.some(function(term) {
        return item[searchField].indexOf(term) === -1;
      });
    });
  }
});

Modified filter (match ANY search term)

app.filter("getMatches", function () {
  return function (items, options) {
    var options = options || {};
    var searchField = options.searchField || "";
    var searchTerms = options.searchTerms || [];
    if (searchField === "" || !searchTerms.length || (searchTerms.length === 1 && searchTerms[0] === '')) {
      return items;
    }
    return items.filter(function (item) {
      return searchTerms.some(function(term) { // notice the subtle difference here
        return item[searchField].indexOf(term) > -1; // and here
      });
    });
  }
});

Supporting HTML

<select multiple ng-model="selectedCategories" ng-options="category for category in categories"></select>

<div class="job-listing" ng-bind="job | json"
     ng-repeat="job in jobs | getMatches:{searchField: 'Categories', searchTerms: selectedCategories}">
</div>