Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

confused about the need for $scope.$apply

Tags:

angularjs

I have an angular controller:

.controller('DashCtrl', function($scope, Auth) {
    $scope.login = function() {
        Auth.login().then(function(result) {
            $scope.userInfo = result;
        });
    };
});

Which is using a service I created:

.service('Auth', function($window) {
    var authContext = $window.Microsoft.ADAL.AuthenticationContext(...);

    this.login = function() {
        return authContext.acquireTokenAsync(...)
            .then(function(authResult) {
                return authResult.userInfo;
            });

    };
});

The Auth service is using a Cordova plugin which would be outside of the angular world. I guess I am not clear when you need to use a $scope.$apply to update your $scope and when you don't. My incorrect assumption was since I had wrapped the logic into an angular service then I wouldn't need it in this instance, but nothing gets updated unless I wrap the $scope.userInfo = statement in a $timeout or $scope.$apply.

Why is it necessary in this case?

like image 304
Dismissile Avatar asked Jan 28 '16 21:01

Dismissile


People also ask

What is scope apply?

$scope. $apply() takes a function or an Angular expression string, and executes it, then calls $scope. $digest() to update any bindings or watchers.

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

$apply() function will execute custom code and then it will call $scope. $digest() function forcefully to check all watch list variables and update variable values in view if any changes found for watch list variables.

What is scope Digest ()?

$scope.$digest() It updates the data binding. It iterates through all the watches and checks any value updated. This will run watcher for the current scope.

What is $scope in angular?

AngularJS Scope The scope is the binding part between the HTML (view) and the JavaScript (controller). The scope is an object with the available properties and methods. The scope is available for both the view and the controller.


1 Answers

From angular's wiki:

AngularJS provides wrappers for common native JS async behaviors:

...

jQuery.ajax() => $http

This is just a traditional async function with a $scope.$apply() called at the end, to tell AngularJS that an asynchronous event just occurred.

So i guess since your Auth service does not use angular's $http, $scope.$apply() isn't called by angular after executing the Async Auth function.

Whenever possible, use AngularJS services instead of native. If you're creating an AngularJS service (such as for sockets) it should have a $scope.$apply() anywhere it fires a callback.

EDIT:

In your case, you should trigger the digest cycle once the model is updated by wrapping (as you did):

Auth.login().then(function(result) {
   $scope.$apply(function(){
      $scope.userInfo = result;
   });
});

Or

Auth.login().then(function(result) {
    $scope.userInfo = result;
    $scope.$apply();
});
like image 187
Daniel Avatar answered Oct 03 '22 07:10

Daniel