aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRosina Bignall2013-01-23 18:18:18 -0600
committerMisko Hevery2013-02-14 14:43:55 -0800
commitace54ff08c4593195b49eadb04d258e6409d969e (patch)
tree60fdeef31aba4aed772821bc029b7a623830b272
parentf5835963d5982003a713dd354eefd376ed39ac02 (diff)
downloadangular.js-ace54ff08c4593195b49eadb04d258e6409d969e.tar.bz2
feat(filter): Add comparison function to filter
Add optional comparator function argument to $filter('filter')(array, expression, comparator) such that the comparator function is used to compare the values and predicates. When true, defaults to equality. When missing defaults to substring matching.
-rw-r--r--src/ng/filter/filter.js80
-rw-r--r--test/ng/filter/filterSpec.js53
2 files changed, 116 insertions, 17 deletions
diff --git a/src/ng/filter/filter.js b/src/ng/filter/filter.js
index 467f6699..c2a06686 100644
--- a/src/ng/filter/filter.js
+++ b/src/ng/filter/filter.js
@@ -32,6 +32,22 @@
* called for each element of `array`. The final result is an array of those elements that
* the predicate returned true for.
*
+ * @param {function(expected, actual)|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.
+ *
+ * Can be one of:
+ *
+ * - `function(expected, actual)`:
+ * The function will be given the object value and the predicate value to compare and
+ * should return true if the item should be included in filtered result.
+ *
+ * - `true`: A shorthand for `function(expected, actual) { return angular.equals(expected, actual)}`.
+ * this is essentially strict comparison of expected and actual.
+ *
+ * - `false|undefined`: A short hand for a function which will look for a substring match in case
+ * insensitive way.
+ *
* @example
<doc:example>
<doc:source>
@@ -39,7 +55,8 @@
{name:'Mary', phone:'800-BIG-MARY'},
{name:'Mike', phone:'555-4321'},
{name:'Adam', phone:'555-5678'},
- {name:'Julie', phone:'555-8765'}]"></div>
+ {name:'Julie', phone:'555-8765'},
+ {name:'Juliette', phone:'555-5678'}]"></div>
Search: <input ng-model="searchText">
<table id="searchTextResults">
@@ -53,9 +70,10 @@
Any: <input ng-model="search.$"> <br>
Name only <input ng-model="search.name"><br>
Phone only <input ng-model="search.phone"å><br>
+ Equality <input type="checkbox" ng-model="strict"><br>
<table id="searchObjResults">
<tr><th>Name</th><th>Phone</th><tr>
- <tr ng-repeat="friend in friends | filter:search">
+ <tr ng-repeat="friend in friends | filter:search:strict">
<td>{{friend.name}}</td>
<td>{{friend.phone}}</td>
<tr>
@@ -75,13 +93,19 @@
it('should search in specific fields when filtering with a predicate object', function() {
input('search.$').enter('i');
expect(repeater('#searchObjResults tr', 'friend in friends').column('friend.name')).
- toEqual(['Mary', 'Mike', 'Julie']);
+ toEqual(['Mary', 'Mike', 'Julie', 'Juliette']);
+ });
+ it('should use a equal comparison when comparator is true', function() {
+ input('search.name').enter('Julie');
+ input('strict').check();
+ expect(repeater('#searchObjResults tr', 'friend in friends').column('friend.name')).
+ toEqual(['Julie']);
});
</doc:scenario>
</doc:example>
*/
function filterFilter() {
- return function(array, expression) {
+ return function(array, expression, comperator) {
if (!(array instanceof Array)) return array;
var predicates = [];
predicates.check = function(value) {
@@ -92,20 +116,43 @@ function filterFilter() {
}
return true;
};
+ switch(typeof comperator) {
+ case "function":
+ break;
+ case "boolean":
+ if(comperator == true) {
+ comperator = function(obj, text) {
+ return angular.equals(obj, text);
+ }
+ break;
+ }
+ default:
+ comperator = function(obj, text) {
+ text = (''+text).toLowerCase();
+ return (''+obj).toLowerCase().indexOf(text) > -1
+ };
+ }
var search = function(obj, text){
- if (text.charAt(0) === '!') {
+ if (typeof text == 'string' && text.charAt(0) === '!') {
return !search(obj, text.substr(1));
}
switch (typeof obj) {
case "boolean":
case "number":
case "string":
- return ('' + obj).toLowerCase().indexOf(text) > -1;
+ return comperator(obj, text);
case "object":
- for ( var objKey in obj) {
- if (objKey.charAt(0) !== '$' && search(obj[objKey], text)) {
- return true;
- }
+ switch (typeof text) {
+ case "object":
+ return comperator(obj, text);
+ break;
+ default:
+ for ( var objKey in obj) {
+ if (objKey.charAt(0) !== '$' && search(obj[objKey], text)) {
+ return true;
+ }
+ }
+ break;
}
return false;
case "array":
@@ -118,7 +165,7 @@ function filterFilter() {
default:
return false;
}
- };
+ };
switch (typeof expression) {
case "boolean":
case "number":
@@ -128,19 +175,18 @@ function filterFilter() {
for (var key in expression) {
if (key == '$') {
(function() {
- var text = (''+expression[key]).toLowerCase();
- if (!text) return;
+ if (!expression[key]) return;
+ var path = key
predicates.push(function(value) {
- return search(value, text);
+ return search(value, expression[path]);
});
})();
} else {
(function() {
+ if (!expression[key]) return;
var path = key;
- var text = (''+expression[key]).toLowerCase();
- if (!text) return;
predicates.push(function(value) {
- return search(getter(value, path), text);
+ return search(getter(value,path), expression[path]);
});
})();
}
diff --git a/test/ng/filter/filterSpec.js b/test/ng/filter/filterSpec.js
index a33358d0..4f357371 100644
--- a/test/ng/filter/filterSpec.js
+++ b/test/ng/filter/filterSpec.js
@@ -66,4 +66,57 @@ describe('Filter: filter', function() {
expect(filter(items, '!isk').length).toBe(1);
expect(filter(items, '!isk')[0]).toEqual(items[1]);
});
+
+ describe('should support comparator', function() {
+
+ it('as equality when true', function() {
+ var items = ['misko', 'adam', 'adamson'];
+ var expr = 'adam';
+ expect(filter(items, expr, true)).toEqual([items[1]]);
+ expect(filter(items, expr, false)).toEqual([items[1], items[2]]);
+
+ var items = [
+ {key: 'value1', nonkey: 1},
+ {key: 'value2', nonkey: 2},
+ {key: 'value12', nonkey: 3},
+ {key: 'value1', nonkey:4},
+ {key: 'Value1', nonkey:5}
+ ];
+ var expr = {key: 'value1'};
+ expect(filter(items, expr, true)).toEqual([items[0], items[3]]);
+
+ var items = [
+ {key: 1, nonkey: 1},
+ {key: 2, nonkey: 2},
+ {key: 12, nonkey: 3},
+ {key: 1, nonkey:4}
+ ];
+ var expr = { key: 1 };
+ expect(filter(items, expr, true)).toEqual([items[0], items[3]]);
+
+ var expr = 12;
+ expect(filter(items, expr, true)).toEqual([items[2]]);
+ });
+
+ it('and use the function given to compare values', function() {
+ var items = [
+ {key: 1, nonkey: 1},
+ {key: 2, nonkey: 2},
+ {key: 12, nonkey: 3},
+ {key: 1, nonkey:14}
+ ];
+ var expr = {key: 10};
+ var comparator = function (obj,value) {
+ return obj > value;
+ }
+ expect(filter(items, expr, comparator)).toEqual([items[2]]);
+
+ expr = 10;
+ expect(filter(items, expr, comparator)).toEqual([items[2], items[3]]);
+
+ });
+
+
+ });
+
});