orange
orange

Reputation: 8080

Angularjs view doesn't update

I'm trying to update a view through a controller that sources its data from a service. For some reason, the view doesn't update when the service's data changes. I've distilled an example from my application here. I've tried all sorts of bindings ($scope.time = TimerService.value, wrapped in a function, using $watch - no success).

Note, in my original app, this is an array of objects and an object's attribute changes.

-- script.js --

var mod = angular.module('mymodule', []);

mod.service('TimerService', function() {
  this.value = 0;
  var self = this;
  setInterval(function() {
    self.value += 1;
  }, 2000)
});

mod.controller('TimerCtrl', ['TimerService', '$scope', function(TimerService, $scope) {
  $scope.time = TimerService.value;
  $scope.$watch(function() {
    return TimerService.value;
  }, function(newValue) {
    $scope.time = newValue;  
  }, true);
  $scope.otherValue = '12345';
}]);


angular.element(document).ready(function() {
  alert('start');
  angular.bootstrap(document, ['mymodule']);
});

-- index.html --

<!DOCTYPE html>
<html>

  <head>
    <script src="./angular.js"></script>
    <link rel="stylesheet" href="style.css" />
    <script src="script.js"></script>
  </head>

  <body>
      <div ng-controller="TimerCtrl">
          <h1>- {{ time }}-</h1>
          <h2>{{ otherValue }}</h2>
      </div>
  </body>

</html>

Upvotes: 1

Views: 5565

Answers (3)

orange
orange

Reputation: 8080

After spending some time with trial and error, I finally found the answer to the problem. In my example above (and my real application), the data gets changed outside of the angular scope (controller button click, http request, etc) which means a digest cycle is not getting kicked off. If I change the code to use $timeout(), it works. Unfortunately, this doesn't entirely solve my problem of the data being changed outside of angular (I guess I need to integrate the rest into angular as well).

Update

I managed to perform changes outside of angular by using rootscope in my service:

$rootscope.$apply(function() {
  // perform variable update here.
  self.value += 1;
});

This successfully propagates to the view.

Upvotes: 1

Whisher
Whisher

Reputation: 32716

Try

var app = angular.module('myApp', []);
            var value = 0;
            var timer = setInterval('Repeater()', 1000);
            var Repeater = function () {
                value++;
                var scope = angular.element(document.getElementById('myApp')).scope();
                console.log(scope);
                scope.$apply(function () {
                        scope.time = value;
                    });
                };
            app.controller('TimerCtrl', ['$scope', function( $scope) {

          }]);

credit to https://stackoverflow.com/a/16520050/356380

Upvotes: 0

D.S
D.S

Reputation: 1150

Try this

$scope.time = TimerService.value;
if(!$scope.$$phase) {
    $scope.$apply();
}

Upvotes: 0

Related Questions