mirror of
https://github.com/Hopiu/angular.js.git
synced 2026-03-16 23:30:23 +00:00
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.
This commit is contained in:
parent
f5835963d5
commit
ace54ff08c
2 changed files with 116 additions and 17 deletions
|
|
@ -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]);
|
||||
});
|
||||
})();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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]]);
|
||||
|
||||
});
|
||||
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
|
|
|||
Loading…
Reference in a new issue