Skip to content
This repository has been archived by the owner on Apr 12, 2024. It is now read-only.

Commit

Permalink
feat(filter): Add comparison function to filter
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
bignall authored and mhevery committed Feb 14, 2013
1 parent f583596 commit ace54ff
Show file tree
Hide file tree
Showing 2 changed files with 116 additions and 17 deletions.
80 changes: 63 additions & 17 deletions src/ng/filter/filter.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,14 +32,31 @@
* 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

This comment has been minimized.

Copy link
@nh2

nh2 Apr 17, 2013

Looks like for me, the first parameter (expected) actually gets passed the value from the array! Description swapped or code wrong?

* 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>
<div ng-init="friends = [{name:'John', phone:'555-1276'},
{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">
Expand All @@ -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>
Expand All @@ -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) {

This comment has been minimized.

Copy link
@EvanZ

EvanZ Feb 21, 2013

"comperator"? Might want to fix that typo

if (!(array instanceof Array)) return array;
var predicates = [];
predicates.check = function(value) {
Expand All @@ -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":
Expand All @@ -118,7 +165,7 @@ function filterFilter() {
default:
return false;
}
};
};
switch (typeof expression) {
case "boolean":
case "number":
Expand All @@ -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]);
});
})();
}
Expand Down
53 changes: 53 additions & 0 deletions test/ng/filter/filterSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -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]]);

});


});

});

0 comments on commit ace54ff

Please sign in to comment.