32
32
* called for each element of `array`. The final result is an array of those elements that
33
33
* the predicate returned true for.
34
34
*
35
+ * @param {function(expected, actual)|true|undefined } comparator Comparator which is used in
36
+ * determining if the expected value (from the filter expression) and actual value (from
37
+ * the object in the array) should be considered a match.
38
+ *
39
+ * Can be one of:
40
+ *
41
+ * - `function(expected, actual)`:
42
+ * The function will be given the object value and the predicate value to compare and
43
+ * should return true if the item should be included in filtered result.
44
+ *
45
+ * - `true`: A shorthand for `function(expected, actual) { return angular.equals(expected, actual)}`.
46
+ * this is essentially strict comparison of expected and actual.
47
+ *
48
+ * - `false|undefined`: A short hand for a function which will look for a substring match in case
49
+ * insensitive way.
50
+ *
35
51
* @example
36
52
<doc:example>
37
53
<doc:source>
38
54
<div ng-init="friends = [{name:'John', phone:'555-1276'},
39
55
{name:'Mary', phone:'800-BIG-MARY'},
40
56
{name:'Mike', phone:'555-4321'},
41
57
{name:'Adam', phone:'555-5678'},
42
- {name:'Julie', phone:'555-8765'}]"></div>
58
+ {name:'Julie', phone:'555-8765'},
59
+ {name:'Juliette', phone:'555-5678'}]"></div>
43
60
44
61
Search: <input ng-model="searchText">
45
62
<table id="searchTextResults">
53
70
Any: <input ng-model="search.$"> <br>
54
71
Name only <input ng-model="search.name"><br>
55
72
Phone only <input ng-model="search.phone"å><br>
73
+ Equality <input type="checkbox" ng-model="strict"><br>
56
74
<table id="searchObjResults">
57
75
<tr><th>Name</th><th>Phone</th><tr>
58
- <tr ng-repeat="friend in friends | filter:search">
76
+ <tr ng-repeat="friend in friends | filter:search:strict ">
59
77
<td>{{friend.name}}</td>
60
78
<td>{{friend.phone}}</td>
61
79
<tr>
75
93
it('should search in specific fields when filtering with a predicate object', function() {
76
94
input('search.$').enter('i');
77
95
expect(repeater('#searchObjResults tr', 'friend in friends').column('friend.name')).
78
- toEqual(['Mary', 'Mike', 'Julie']);
96
+ toEqual(['Mary', 'Mike', 'Julie', 'Juliette']);
97
+ });
98
+ it('should use a equal comparison when comparator is true', function() {
99
+ input('search.name').enter('Julie');
100
+ input('strict').check();
101
+ expect(repeater('#searchObjResults tr', 'friend in friends').column('friend.name')).
102
+ toEqual(['Julie']);
79
103
});
80
104
</doc:scenario>
81
105
</doc:example>
82
106
*/
83
107
function filterFilter ( ) {
84
- return function ( array , expression ) {
108
+ return function ( array , expression , comperator ) {
85
109
if ( ! ( array instanceof Array ) ) return array ;
86
110
var predicates = [ ] ;
87
111
predicates . check = function ( value ) {
@@ -92,20 +116,43 @@ function filterFilter() {
92
116
}
93
117
return true ;
94
118
} ;
119
+ switch ( typeof comperator ) {
120
+ case "function" :
121
+ break ;
122
+ case "boolean" :
123
+ if ( comperator == true ) {
124
+ comperator = function ( obj , text ) {
125
+ return angular . equals ( obj , text ) ;
126
+ }
127
+ break ;
128
+ }
129
+ default :
130
+ comperator = function ( obj , text ) {
131
+ text = ( '' + text ) . toLowerCase ( ) ;
132
+ return ( '' + obj ) . toLowerCase ( ) . indexOf ( text ) > - 1
133
+ } ;
134
+ }
95
135
var search = function ( obj , text ) {
96
- if ( text . charAt ( 0 ) === '!' ) {
136
+ if ( typeof text == 'string' && text . charAt ( 0 ) === '!' ) {
97
137
return ! search ( obj , text . substr ( 1 ) ) ;
98
138
}
99
139
switch ( typeof obj ) {
100
140
case "boolean" :
101
141
case "number" :
102
142
case "string" :
103
- return ( '' + obj ) . toLowerCase ( ) . indexOf ( text ) > - 1 ;
143
+ return comperator ( obj , text ) ;
104
144
case "object" :
105
- for ( var objKey in obj ) {
106
- if ( objKey . charAt ( 0 ) !== '$' && search ( obj [ objKey ] , text ) ) {
107
- return true ;
108
- }
145
+ switch ( typeof text ) {
146
+ case "object" :
147
+ return comperator ( obj , text ) ;
148
+ break ;
149
+ default :
150
+ for ( var objKey in obj ) {
151
+ if ( objKey . charAt ( 0 ) !== '$' && search ( obj [ objKey ] , text ) ) {
152
+ return true ;
153
+ }
154
+ }
155
+ break ;
109
156
}
110
157
return false ;
111
158
case "array" :
@@ -118,7 +165,7 @@ function filterFilter() {
118
165
default :
119
166
return false ;
120
167
}
121
- } ;
168
+ } ;
122
169
switch ( typeof expression ) {
123
170
case "boolean" :
124
171
case "number" :
@@ -128,19 +175,18 @@ function filterFilter() {
128
175
for ( var key in expression ) {
129
176
if ( key == '$' ) {
130
177
( function ( ) {
131
- var text = ( '' + expression [ key ] ) . toLowerCase ( ) ;
132
- if ( ! text ) return ;
178
+ if ( ! expression [ key ] ) return ;
179
+ var path = key
133
180
predicates . push ( function ( value ) {
134
- return search ( value , text ) ;
181
+ return search ( value , expression [ path ] ) ;
135
182
} ) ;
136
183
} ) ( ) ;
137
184
} else {
138
185
( function ( ) {
186
+ if ( ! expression [ key ] ) return ;
139
187
var path = key ;
140
- var text = ( '' + expression [ key ] ) . toLowerCase ( ) ;
141
- if ( ! text ) return ;
142
188
predicates . push ( function ( value ) {
143
- return search ( getter ( value , path ) , text ) ;
189
+ return search ( getter ( value , path ) , expression [ path ] ) ;
144
190
} ) ;
145
191
} ) ( ) ;
146
192
}
0 commit comments