1

I've got a service for my websocket connection and this service returns in a function the actual state whether the client is actual connected or not. I've simplified my code and these snippets are a small example of my problem:

myApp.factory('Websocket', function() {
    //the status boolean whether connected or not
    var bool = true;

    //small mock for the status change
    setInterval(function() {
        bool = !bool;
    }, 1000);

    //i've made the value of the status variable accessable in a function or the variable itself
    return {
        status: function() {
            return bool;   
        },
        var: bool
    }
});

Now i tried to apply the status value to my scope in the controller:

myApp.controller('Ctrl', function(Websocket, $scope) {
   //method 1
   $scope.status = Websocket.status();

   //method 2
   $scope.$watch(function() {
     return Websocket.status();
   }, function(newVal) {
     $scope.status = newVal;
   });
});

...but both methods don't work and don't update the $scope variable for this html:

<div ng-app="myApp">
    <div ng-controller="Ctrl">
      method1: {{status}}
    </div>
</div>

This is a codepen: http://codepen.io/anon/pen/bVjaBa?editors=101

Thanks for your help!

2 Answers 2

1

The problem is that any "external" change to data watched by Angular has to call scope.$apply() for the watchers to update (here the watchers are the UI from the {{status}} expression). In the codepen the solution is simple: Make the service depend on the $rootScope and call $rootScope.$apply() in the interval function:

myApp.factory('Websocket', function($rootScope) {
    ...
    setInterval(function() {
        bool = !bool;
        $rootScope.$apply();
    }, 1000);
    ...
});

Something similar has to be done with the real service, key concepts being: (1) you have to call $apply() and (2) having no access to a specific scope, just use the $rootScope.

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks for your help!
I'd go with $rootScope.$digest right off the bat instead of $apply - as all you're doing is jumping through a try/catch statement to reach the same result. source. Not really costly but, there's no real reason for doing it.
1

The problem is as Nikos mentioned: you are changing the variable's value outside of the digest loop, so angular is not following the changes.

Using $scope.$apply is one option, but in this case I would prefer using $interval instead of setInterval.

myApp.factory('Websocket', function($interval) {
  var bool = true;
  $interval(function() {
    bool = !bool;
  }, 1000);

  return {
    status: function() {
        return bool;   
    },
    var: bool
  }
});

See it working here.

1 Comment

Thanks for your help!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.