Regression in filterFilter 1.3.6 changes when using a custom comparator function #11752
Description
When I upgraded from an earlier version of 1.3.x (1.3.0) to the latest version (1.3.15), several uses of filterFilter were broken. I traced the regression back to the changes that were implemented in 1.3.6 (specifically I think it was f7cf846). I believe this same issue probably effects 1.4.x as well, although I have not tested it.
In my use case, I have a filter that looks like this:
ng-repeat="... | filter:{Slot: slot}:modelEquals"
What's happening here is that Slot
, the property, is a reference to a model object on the array elements. This then gets compared to slot
, the iterator variable, from a wrapping ng-repeat. The comparison function is modelEquals
, which does a comparison based on the object prototype and ID property. The specifics of the comparison function are not relevant because my problem is that the comparison function is never called!
Here are two jsfiddles that reproduce the problem with as little complexity as I could manage and still reproduce the problem:
1.3.6 - This shows the problem. You can see that my custom comparison function is never called.
http://jsfiddle.net/thcjthcy/17/
1.3.5 - This is the exact same functional code (just different explanatory text), but referencing 1.3.5. Notice that my comparison function is called as expected.
http://jsfiddle.net/thcjthcy/16/
I debugged into the 1.3.6+ code a bit, and I think the problem comes when the deepCompare
function recurses whenever the expected value is an object (https://github.com/angular/angular.js/blob/v1.3.15/src/ng/filter/filter.js#L216). I believe I understand why it does this (wants to support comparisons of nested properties), however in my case the expected value is a complex object, and the comparison seems to get lost in the woods, so to speak, and my comparison function is never called. In the 1.3.5 code, since I don't believe it recurses, my comparison function is called with the top-level expected and actual object values.
I believe this is a bug because it doesn't match the documentation, or at least my understanding of it. Specifically:
https://github.com/angular/angular.js/blob/v1.3.15/src/ng/filter/filter.js#L32
Note that a named property will match properties on the same level only, while the special $ property will match properties on the same level or deeper
I am using a named property, and yet the code is recursing to a deeper level instead of calling my comparison function on the top-level property.
For the time being, my work-around is to stay on 1.3.5. If this is just how filterFilter is supposed to work now, and there won't be an "opposite of $" kind of marker that lets me short-circuit the deep comparison, I would probably work around this by writing a filter function which takes the property name and expected value and does the key indexing into the array item (actual) manually. This isn't a huge amount of work, but I wanted to see if the built-in filterFilter was supposed to be able to support this use case before I ditched it.