0

I have this simple snippet:

HTML:

<div ng-app="myApp" ng-controller="SampleController">
   <p>{{val1}}</p>
   <p>{{val2}}</p>
   <input type="button" value="Update" ng-click="update()" />
</div>

Javascript:

var app = angular.module('myApp', []);

app.controller('SampleController', ['$scope', function($scope) {

    $scope.val1 = "Not updated";
    $scope.val2 = "Not updated";

    $scope.update = function () {
        $scope.val1 = "Updated outside!";

        setTimeout(function () {
            $scope.val2 = "Update inside!";
        }, 1);
    };
}]);

snippet also in jsfiddle.

If I click in the update button only the value val1 is updated in the html. How to fix that? But most importantly, why is this happening?

PS: setTimeout is just a simplification of the problem. In fact the question is about any custom components that has callback functions.

Jonny Piazzi
  • 3,684
  • 4
  • 34
  • 81

1 Answers1

2

setTimeout doesn't trigger a digest cycle, so no the view will not update. Angular comes with a built in $timeout module - use that and a digest cycle will execute and your view will update.

To use:

app.controller('SampleController', ['$scope', '$timeout', function($scope, $timeout) {
    $timeout(function() { $scope.val2 = "see?" }, 5000);
}]);
tymeJV
  • 103,943
  • 14
  • 161
  • 157
  • Nice, but if i'm using something else, like jQuery.ajax.success or $http.get. Or something that there is no hack (like '$timeout') by angularjs? – Jonny Piazzi Mar 01 '17 at 21:58
  • Well, `http.get` will trigger a digest cycle - so your safe there. Basically, anything outside of Angular modules won't trigger the cycle, so you'll need to work around it with hacks or write your own angular module – tymeJV Mar 01 '17 at 21:59
  • Is there somehow to notify 'digest cycle' that a scope change was maded? – Jonny Piazzi Mar 01 '17 at 22:00
  • You can force digest cycles with `$scope.$apply()` - but that's a hack and errors can happen because of it - `$timeout` is generally a safe way to force a digest cycle. – tymeJV Mar 01 '17 at 22:01
  • I would read: https://www.sitepoint.com/understanding-angulars-apply-digest/ – tymeJV Mar 01 '17 at 22:01
  • I made a update. If you comply, I can make this answer as correct. – Jonny Piazzi Mar 01 '17 at 22:21
  • But your edit is wrong - you shouldn't use `$scope.apply()` to force a digest when there is an angular module specifically to not do that. You should only force the digest cycle if you *have* to. – tymeJV Mar 01 '17 at 23:07