codelord.net

Code, Angular, iOS and more by Aviv Ben-Yosef

Replacing Angular's Deep Watches with the $doCheck Lifecycle Hook

| Comments

After digging into Angular’s components $onChanges lifecycle hook to show how you can replace a regular shallow $scope.$watch with it, let’s see what the latest Angular has to offer when it comes to deep watches.

Deep watches are what Angular does when you supply a third argument to $scope with the value of true:

1
$scope.$watch(() => this.foo, this.handleChange, true);

Note: I’m using ES6’s arrow functions for brevity, but obviously you don’t have to.

By using deep watches, we can ask Angular to keep track of changes happening inside an object, by mutating it, instead of only notifying us when the object’s reference has changed (which is the default behavior of $scope.$watch).

While it’s possible to use $onChanges for being notified about changes to references on bindings, there’s no easy way to do it for mutations without $scope.$watch.

The problem is that Angular is moving off $scope, and we would like to be able to use it only where it’s really a must, so what can we do?

First, think whether you really need to be mutating state. In a lot of scenarios, using immutable models makes a lot more sense, and using one-way data flow makes code easier to maintain.

Quick aside: If you’d like to keep getting posts about the latest and greatest in Angular 1.x, and especially hear about one-way data flow, subscribe to my newsletter:

Subscribe to get the latest about modern Angular 1.x

But, in cases you have to keep using deep watches, there’s some more modern solution offered by Angular. The $doCheck lifecycle hook is a bit peculiar. It’s basically a hook that Angular calls on each turn of the digest cycle, for us to add our logic in it. That allows us to regularly check if anything has changed and requires our component’s attention.

What this enables us to do, in practice, is replace our deep watches. Here’s an example:

1
2
3
4
5
6
7
8
9
10
11
12
function FooCtrl() {
  var previousFoo = undefined;

  this.$onInit = () => { previousFoo = angular.copy(this.foo) };

  this.$doCheck = () => {
    if (!angular.equals(this.foo, previousFoo)) {
      this.handleFooChange();
      previousFoo = angular.copy(this.foo);
    }
  };
}

Now, this is a bit of a mouthful. As you can see, when we want to drop deep watches we actually have to do quite some work on our own: keep track of the previous value, make the comparison, and make sure we are holding a copy of the value (otherwise we’ll never see changes).

Angular is basically telling us that deep watches belong to the past, and that there’s a way to keep doing them without scopes, but you’ll need to work for it. Personally, I don’t love the extra typing, but I think that if you have to keep using deep watches for now and are upgrading your code to the latest 1.6 standards, you should probably be doing this.

Nowadays, a modern Angular app should be making very small use of scopes, and deep watches are a big red flag usually. This makes sense both from the standpoint of moving to a one-way data flow, and for keeping your options open when it comes to migrating to Angular 2+ down the road.


You want to do Angular the right way.
You hate spending time working on a project, only to find it’s completely wrong a month later.
But, as you try to get things right, you end up staring at the blinking cursor in your IDE, not sure what to type.
Every line of code you write means making decisions, and it’s paralyzing.

You look at blog posts, tutorials, videos, but each is a bit different.
Now you need to reverse engineer every advice to see what version of Angular it was written for, how updated it is, and whether it fits the current way of doing things.

What if you knew the Angular Way of doing things?
Imagine knocking down your tasks and spending your brain cycles on your product’s core.
Wouldn’t it be nice to know Angular like a second language?

You can write modern, clean and future-ready Angular right now.
Sign up below and get more of these helpful posts, free!
Always up to date and I’ve already done all the research for you.

And be the first the hear about my Modern Angular 1.x book – writing future proof Angular right now.

Subscribe to get the latest about modern Angular 1.x

Comments