Skip to content
This repository was archived by the owner on Apr 12, 2024. It is now read-only.
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 7d3b745

Browse files
committedDec 11, 2014
fix(filterFilter): make $ match properties on deeper levels as well
Closes #10401
1 parent aac3c4a commit 7d3b745

File tree

2 files changed

+29
-21
lines changed

2 files changed

+29
-21
lines changed
 

‎src/ng/filter/filter.js

+15-13
Original file line numberDiff line numberDiff line change
@@ -14,17 +14,19 @@
1414
*
1515
* Can be one of:
1616
*
17-
* - `string`: The string is evaluated as an expression and the resulting value is used for substring match against
18-
* the contents of the `array`. All strings or objects with string properties in `array` that contain this string
19-
* will be returned. The predicate can be negated by prefixing the string with `!`.
17+
* - `string`: The string is used for matching against the contents of the `array`. All strings or
18+
* objects with string properties in `array` that match this string will be returned. This also
19+
* applies to nested object properties.
20+
* The predicate can be negated by prefixing the string with `!`.
2021
*
2122
* - `Object`: A pattern object can be used to filter specific properties on objects contained
2223
* by `array`. For example `{name:"M", phone:"1"}` predicate will return an array of items
2324
* which have property `name` containing "M" and property `phone` containing "1". A special
2425
* property name `$` can be used (as in `{$:"text"}`) to accept a match against any
25-
* property of the object. That's equivalent to the simple substring match with a `string`
26-
* as described above. The predicate can be negated by prefixing the string with `!`.
27-
* For Example `{name: "!M"}` predicate will return an array of items which have property `name`
26+
* property of the object or its nested object properties. That's equivalent to the simple
27+
* substring match with a `string` as described above. The predicate can be negated by prefixing
28+
* the string with `!`.
29+
* For example `{name: "!M"}` predicate will return an array of items which have property `name`
2830
* not containing "M".
2931
*
3032
* - `function(value, index)`: A predicate function can be used to write arbitrary filters. The
@@ -39,10 +41,10 @@
3941
*
4042
* - `function(actual, expected)`:
4143
* The function will be given the object value and the predicate value to compare and
42-
* should return true if the item should be included in filtered result.
44+
* should return true if both values should be considered equal.
4345
*
44-
* - `true`: A shorthand for `function(actual, expected) { return angular.equals(expected, actual)}`.
45-
* this is essentially strict comparison of expected and actual.
46+
* - `true`: A shorthand for `function(actual, expected) { return angular.equals(actual, expected)}`.
47+
* This is essentially strict comparison of expected and actual.
4648
*
4749
* - `false|undefined`: A short hand for a function which will look for a substring match in case
4850
* insensitive way.
@@ -169,7 +171,7 @@ function createPredicateFn(expression, comparator, matchAgainstAnyProp) {
169171
return predicateFn;
170172
}
171173

172-
function deepCompare(actual, expected, comparator, matchAgainstAnyProp) {
174+
function deepCompare(actual, expected, comparator, matchAgainstAnyProp, dontMatchWholeObject) {
173175
var actualType = typeof actual;
174176
var expectedType = typeof expected;
175177

@@ -188,11 +190,11 @@ function deepCompare(actual, expected, comparator, matchAgainstAnyProp) {
188190
var key;
189191
if (matchAgainstAnyProp) {
190192
for (key in actual) {
191-
if ((key.charAt(0) !== '$') && deepCompare(actual[key], expected, comparator)) {
193+
if ((key.charAt(0) !== '$') && deepCompare(actual[key], expected, comparator, true)) {
192194
return true;
193195
}
194196
}
195-
return false;
197+
return dontMatchWholeObject ? false : deepCompare(actual, expected, comparator, false);
196198
} else if (expectedType === 'object') {
197199
for (key in expected) {
198200
var expectedVal = expected[key];
@@ -202,7 +204,7 @@ function deepCompare(actual, expected, comparator, matchAgainstAnyProp) {
202204

203205
var keyIsDollar = key === '$';
204206
var actualVal = keyIsDollar ? actual : actual[key];
205-
if (!deepCompare(actualVal, expectedVal, comparator, keyIsDollar)) {
207+
if (!deepCompare(actualVal, expectedVal, comparator, keyIsDollar, keyIsDollar)) {
206208
return false;
207209
}
208210
}

‎test/ng/filter/filterSpec.js

+14-8
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,8 @@ describe('Filter: filter', function() {
9090
var items = [{person: {name: 'John'}},
9191
{person: {name: 'Rita'}},
9292
{person: {name: 'Billy'}},
93-
{person: {name: 'Joan'}}];
93+
{person: {name: 'Joan'}},
94+
{person: {name: {first: 'John', last: 'Doe'}}}];
9495
expect(filter(items, {person: {name: 'Jo'}}).length).toBe(2);
9596
expect(filter(items, {person: {name: 'Jo'}})).toEqual([
9697
{person: {name: 'John'}}, {person: {name: 'Joan'}}
@@ -136,14 +137,19 @@ describe('Filter: filter', function() {
136137
});
137138

138139

139-
it('should respect the depth level of a "$" property', function() {
140-
var items = [{person: {name: 'Annet', email: 'annet@example.com'}},
141-
{person: {name: 'Billy', email: 'me@billy.com'}},
142-
{person: {name: 'Joan', email: {home: 'me@joan.com', work: 'joan@example.net'}}}];
143-
var expr = {person: {$: 'net'}};
140+
it('should match any properties on same or deeper level for given "$" property', function() {
141+
var items = [{level1: 'test', foo1: 'bar1'},
142+
{level1: {level2: 'test', foo2:'bar2'}, foo1: 'bar1'},
143+
{level1: {level2: {level3: 'test', foo3: 'bar3'}, foo2: 'bar2'}, foo1: 'bar1'}];
144144

145-
expect(filter(items, expr).length).toBe(1);
146-
expect(filter(items, expr)).toEqual([items[0]]);
145+
expect(filter(items, {$: 'ES'}).length).toBe(3);
146+
expect(filter(items, {$: 'ES'})).toEqual([items[0], items[1], items[2]]);
147+
148+
expect(filter(items, {level1: {$: 'ES'}}).length).toBe(2);
149+
expect(filter(items, {level1: {$: 'ES'}})).toEqual([items[1], items[2]]);
150+
151+
expect(filter(items, {level1: {level2: {$: 'ES'}}}).length).toBe(1);
152+
expect(filter(items, {level1: {level2: {$: 'ES'}}})).toEqual([items[2]]);
147153
});
148154

149155

0 commit comments

Comments
 (0)
This repository has been archived.