$apply vs $digest in directive testing

AngularjsAngularjs Directive

Angularjs Problem Overview


If I have a directive that responds to the status of a particular attribute on the scope, and I want to change that attribute in my test and verify that it responds correctly, which is the best way of doing that change?

I've seen both these patterns:

scope.$apply(function() {
    scope.myAttribute = true;
});

and

scope.myAttribute = true;
scope.$digest();

What is the difference between them, and which is better and why?

Angularjs Solutions


Solution 1 - Angularjs

scope.$digest() will fire watchers on the current scope, and on all of its children, too. scope.$apply will evaluate passed function and run $rootScope.$digest().

The first one is faster, as it needs to evaluate watchers for current scope and its children. The second one is slower, as it needs to evaluate watchers for$rootScope and all it's child scopes.

When an error occurs in one of the watchers and you use scope.$digest, it's not handled via $exceptionHandler service, so you need to handle exception yourself. scope.$apply uses a try-catch block internally and passes all exceptions to $exceptionHandler.

Solution 2 - Angularjs

As the documentation itself mentions $digest cycle is peformed any time you do $scope.$apply. As per developer guide on [scope][1]

> After evaluating the expression, the $apply method performs a $digest. > In the $digest phase the scope examines all of the $watch expressions > and compares them with the previous value.

And as per the Scope API [documentation][2]

> Usually you don't call $digest() directly in controllers or in > directives. Instead a call to $apply() (typically from within a > directives) will force a $digest().

So you should not explicitly call $digest, you calling $apply method would trigger a digest cycle. [1]: http://docs.angularjs.org/guide/scope [2]: http://docs.angularjs.org/api/ng.$rootScope.Scope

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionDaniel RosemanView Question on Stackoverflow
Solution 1 - AngularjsTadeusz WójcikView Answer on Stackoverflow
Solution 2 - AngularjsChandermaniView Answer on Stackoverflow