AngularJS: $watch, $digest and $apply

Kindly ignore this post..this is just an angular.copy(benlesh_blog_post) 😉

I would like to thank benlesh for such a great post explaining what is watch,digest and apply in an clear cut manner.

For my reference i am just posting necessary content here.

What is a $watch?

Let’s talk about this first. $watch is arguably the most important internal feature of Angular. $watches can be used to watch any value, and trigger a function call when that value changes. A $watch can be set up from any $scope by calling $scope.$watch() as shown below.

Setting up a $watch

There are two ways to set up a watch, by expression, or by function. Technically, they both do the same thing. If you pass an expression (a string), it will be evaluated against $scope and converted to a function to be watched. If you pass a function, it just watches that function, with no conversion necessary.

By Expression

The following will watch 'foo'. Which is an expression evaluated against $scope.

  1. //$scope.$watch(<function/expression>, <handler>);
  2.  
  3. $scope.$watch(‘foo’, function(newVal, oldVal) {
  4. console.log(newVal, oldVal);
  5. });

By Function

To set up a $watch by function, you can do the following, which is technically the same as what is shown above:

  1. $scope.$watch(function() {
  2. return $scope.foo;
  3. }, function(newVal, oldVal) {
  4. console.log(newVal, oldVal);
  5. });

Facts about $watch:

  • A watcher can evaluate any value.
  • A watcher’s handler can execute anything when aforementioned value has changed.
  • All watchers are evaluated when $digest() is called.
  • If the first argument of a $watch is a string, it is $eval’ed into a function prior to registration. It’s functionally equivalent to passing a function as the first argument, just with an extra step internally.

What is $digest?

At it’s core, the important thing to know about $digest is that it loops through all watchers on the scope it was called on and it’s child scopes. and evaluates them to see if they’ve changed, executing their handlers if they have. That’s the important part you need to know.

How to call $digest:

  1. $scope.$digest();

    What is $apply?

    Simply put, it’s a wrapper around $rootScope.$digest that evaluates any expression passed to it prior to calling $digest(). That’s it.  So, if you’re calling it by itself without passing an argument to it, you may as well just call $digest().

    How to call $apply:

    1. $scope.$apply(‘foo = “test”‘);
    2. //or
    3. $scope.$apply(function(scope) {
    4. scope.foo = ‘test’;
    5. });
    6. //or
    7. $scope.$apply(function(){
    8. $scope.foo = ‘test’;
    9. });

When to use $apply vs $digest?

$scope.$digest should rarely be used outside of some very specific instances. Such as an isolated scope in a directive that might want to only update itself. Or, in an extreme edge case if a scope object has been created for some other isolated purpose. $scope.$apply or $rootScope.$digest should be favored most of the time, as the general desired effect is to update an entire view or model.

You do need to use it if you are going to run code in a new turn. And only if that turn isn’t being created from a method in the AngularJS library. Inside that new turn, you should wrap your code in $scope.$apply(). Here is an example. We are usingsetTimeout, which will execute a function in a new turn after a delay. Since Angular doesn’t know about that new turn, the update will not be reflected.

function Ctrl($scope) {
  $scope.message = "Waiting 2000ms for update";
    
    setTimeout(function () {
        $scope.message = "Timeout called!";
        // AngularJS unaware of update to $scope
    }, 2000);
}

But, if we wrap the code for that turn in $scope.$apply(), the change will be noticed, and the page is updated.

function Ctrl($scope) {
  $scope.message = "Waiting 2000ms for update";
    
    setTimeout(function () {
        $scope.$apply(function () {
            $scope.message = "Timeout called!";
        });
    }, 2000);
}
http://www.sitepoint.com/understanding-angulars-apply-digest/
Advertisements

One thought on “AngularJS: $watch, $digest and $apply

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s