Question

In my angular app, I have a $scope variable user with a name.

If I set this variable to "test" on click:

<a href="#" ng-click="setUser()">Set User</a>

with the function

$scope.user = {
  name: 'blank'
}

$scope.setUser = function(name) {
  $scope.user.name = name
}

This works fine. However, if I set this inside a promise.then()*, it appears to set the variable correctly, but Angular does not update it in the view until I have performed another action on $scope.user.

<a href="#" ng-click="startLogin()">Set User</a>

Now calls a new function, startLogin()

$scope.user = {
  name: 'blank';
};

$scope.setUser = function(name) {
  $scope.user.name = name;
};

$scope.startLogin = function() {
  var promise = Kinvey.ping();
  promise.then(function(response) {
    console.log('success');
    $scope.setUser('test');
  });
};

After doing it this way. The {{user.name}} field in the view is still "blank". I also tested the following:

  • $scope is alive and well in the function, when I log it to the console.
  • Also logging $scope.user returns correctly, showing that the variable has changed.
  • Interestingly, the view finally changes the second time I click.
  • I could also solve this by adding $scope.$apply(), But that seems like the wrong way to fix this.

* I'm using Kinvey which uses a syntax similar or identical to CommonJS's promise.then()

Was it helpful?

Solution

The two way bindings get updated during an angular digest cycle. These cycles get triggered by DOM events bound to directives, or other entities participating in the Angular ecosystem.

So the "magic" that Angular provides, is just automatic triggering of that digest cycle. You can trigger the digest cycle with $scope.apply:

promise.then(function(response) {
  $scope.$apply(function() {
     console.log('success');
     $scope.setUser('test');
  });
});

This is the recommended approach when dealing with 3rd party libraries.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top