Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why do i have to call $scope.$digest() here?

I created a directive for showing tooltips:

app.directive('tooltip',function(){
    return{
        restrict: 'A',
        link: function(scope,element,attr){
            element.bind('mouseenter',function(e){

                scope.setStyle(e);

            });
        }
    }
});

The corresponding setStyle() function:

$scope.setStyle = function(e){
    $scope.style = {
        position: 'absolute',
        // some other styles
    };

    $scope.$digest();
};

$scope.style is applied to this:

<span ng-style="style">I am a tooltip</span>

which is part of my view, handled by the controller who owns $scope.style

Why do i have to call $digest() in order to apply the changes to $scope.style, which was declared and initialized earlier?

like image 849
user2422960 Avatar asked Sep 13 '13 11:09

user2422960


People also ask

What is scope Digest ()?

At key points in your application AngularJS calls the $scope. $digest() function. This function iterates through all watches and checks if any of the watched variables have changed. If a watched variable has changed, a corresponding listener function is called.

What is the difference between Digest () and apply () Why would you ever call Digest () on a scope?

$digest() gets called without any arguments. $apply() takes a function that it will execute before doing any updates. The other difference is what they affect. $digest() will update the current scope and any child scopes.

What is the difference between Digest () and apply ()?

$digest() is faster than $apply(), since $apply() triggers watchers on the entire scope chain while $digest() triggers watchers on the current scope and its children(if it has).

How do you fix $Digest already in progress?

There are a few ways to deal with this. The easiest way to deal with this is to use the built in $timeout, and a second way is if you are using underscore or lodash (and you should be), call the following: $timeout(function(){ //any code in here will automatically have an apply run afterwards });

How does $scope $Digest () work?

The $scope.$digest () function iterates through all the watches in the $scope object, and its child $scope objects (if it has any). When $digest () iterates over the watches, it calls the value function for each watch.

How does $scope $apply () work?

Note: $scope.$apply () automatically calls $rootScope.$digest (). The $apply () function comes in two flavors. The first one takes a function as an argument, evaluates it, and triggers a $digest cycle. The second version does not take any arguments and just starts a $digest cycle when called.

What is the $scope $digest () function in AngularJS?

At key points in your application AngularJS calls the $scope.$digest () function. This function iterates through all watches and checks if any of the watched variables have changed. If a watched variable has changed, a corresponding listener function is called.

What is the difference between $scope $apply and $scope-$Digest?

The $scope.$apply () function takes a function as parameter which is executed, and after that $scope.$digest () is called internally. That makes it easier for you to make sure that all watches are checked, and thus all data bindings refreshed.


2 Answers

Because the callback attached to the mouseenter event is outside of angular's scope; angular has no idea when that function runs/ends so the digest cycle is never ran.

Calling $digest or $apply tells angular to update bindings and fire any watches.

like image 71
noj Avatar answered Oct 09 '22 05:10

noj


element.bind() means listen for specific browser event and execute callback when this event is dispatched on element. Nowhere in this chain of events Angular is included - it does not know that the event happened. Therefore you must tell it about the event explicitly. However, in most cases you should use $scope.$apply() not $scope.$digest(), especially when you're not sure about it.

Here is more appropriate code for your situation:

app.directive('tooltip',function(){
    return{
        restrict: 'A',
        link: function(scope,element,attr){
            element.bind('mouseenter',function(e){
                scope.setStyle(e);
                scope.$apply();
            });
        }
    }
});

and setStyle():

$scope.setStyle = function(e){
    $scope.style = {
        position: 'absolute',
        // some other styles
    };
};
like image 30
package Avatar answered Oct 09 '22 06:10

package