From 167131cf154e6a90d265f047486aa5c40f816bb6 Mon Sep 17 00:00:00 2001 From: Justin Ridgewell Date: Tue, 17 Dec 2013 10:39:48 -0500 Subject: [PATCH] feat(filter): allow filtering of an object Allow ng.filter to filter an object as well as an array. Before, an object would need to be converted into an array before filtering. Closes #2694. --- src/ng/filter/filter.js | 27 +++++++++++++-------------- test/ng/filter/filterSpec.js | 6 ++++++ 2 files changed, 19 insertions(+), 14 deletions(-) diff --git a/src/ng/filter/filter.js b/src/ng/filter/filter.js index aa662f8c2824..df59d68a3278 100644 --- a/src/ng/filter/filter.js +++ b/src/ng/filter/filter.js @@ -6,11 +6,11 @@ * @kind function * * @description - * Selects a subset of items from `array` and returns it as a new array. + * Selects a subset of items from `collection` and returns it as a new array. * - * @param {Array} array The source array. + * @param {Array|Object} collection The source collection. * @param {string|Object|function()} expression The predicate to be used for selecting items from - * `array`. + * `collection`. * * Can be one of: * @@ -19,7 +19,7 @@ * will be returned. The predicate can be negated by prefixing the string with `!`. * * - `Object`: A pattern object can be used to filter specific properties on objects contained - * by `array`. For example `{name:"M", phone:"1"}` predicate will return an array of items + * by `collection`. For example `{name:"M", phone:"1"}` predicate will return an array of items * which have property `name` containing "M" and property `phone` containing "1". A special * property name `$` can be used (as in `{$:"text"}`) to accept a match against any * property of the object. That's equivalent to the simple substring match with a `string` @@ -28,12 +28,12 @@ * not containing "M". * * - `function(value, index)`: A predicate function can be used to write arbitrary filters. The - * function is called for each element of `array`. The final result is an array of those - * elements that the predicate returned true for. + * function is called for each element of `collection`. The final result is an array of those + * values that the predicate returned true for. * * @param {function(actual, expected)|true|undefined} comparator Comparator which is used in * determining if the expected value (from the filter expression) and actual value (from - * the object in the array) should be considered a match. + * the object in the collection) should be considered a match. * * Can be one of: * @@ -116,8 +116,8 @@ */ function filterFilter() { - return function(array, expression, comparator) { - if (!isArray(array)) return array; + return function(collection, expression, comparator) { + if (!isObject(collection)) return collection; var comparatorType = typeof(comparator), predicates = []; @@ -208,15 +208,14 @@ function filterFilter() { predicates.push(expression); break; default: - return array; + return collection; } var filtered = []; - for ( var j = 0; j < array.length; j++) { - var value = array[j]; - if (predicates.check(value, j)) { + forEach(collection, function(value, index) { + if (predicates.check(value, index)) { filtered.push(value); } - } + }, this); return filtered; }; } diff --git a/test/ng/filter/filterSpec.js b/test/ng/filter/filterSpec.js index 4249be8ef2c3..295e7d27eeab 100644 --- a/test/ng/filter/filterSpec.js +++ b/test/ng/filter/filterSpec.js @@ -44,6 +44,12 @@ describe('Filter: filter', function() { expect(filter(items, {name: 'b'})[0].name).toBe('abc'); }); + it('should filter an object', function() { + var items = {0: {name: 'a'}, 1: {name: 'abc', done: true}}; + expect(filter(items, function(i) {return i.done;}).length).toBe(1); + expect(filter(items, 'a').length).toBe(2); + }); + it('should take function as predicate', function() { var items = [{name: 'a'}, {name: 'abc', done: true}]; expect(filter(items, function(i) {return i.done;}).length).toBe(1);