
Angular 1 - Custom Compare in $watch
Sometimes you run into a situation where you need to define a custom compare function for $watch to use in Angular 1 change detection.
This was the case for me when I needed to check for changes on a rather deeply nested class.
The Problem
Angular 1 uses $scope.$watch
to actively check for changes.
In my scenario, the built in equality checker had a really hard time with my class. So much so, that it would cause a Max call size exceeded
error every time it tried to run $watch
.
We already had a function that would compare only the attributes on the class that mattered, but $watch
doesn't support custom comparators.
The Solution
You'll need to keep a copy of the previous state somewhere. We have a service that has the original copy of the class, so we used that to determine if the local copy changed.
Here's what it looks like:
Warning - your equals function will run on every digest cycle, so perf matters. Return early!
Here, we provide $watch
with a function that returns a value. Angular will keep track of that value for you. We are going to take advantage of that and simply return a boolean that changes when our custom compare function says that the object has changed.
After you determine that a change has happened, don't forget to update your previous version
Final Thoughts
This is a simple trick that can get you out of a bind, but again, be very mindful of how your build your custom comparator logic.