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.

comments powered by Disqus