0

Hello I'm trying out databinding with AngularJS in combination with an websocket. When the Websocket fires a response, the data should be displayed on a site, but it doesn't work the way I thought.

This is my JS:

 function WebApp() {
  this.webSocket = null;
  this.workdata = null;

  var that = this;


  this.AngularApp = angular.module('AngularApp', []);
  this.AngularApp.controller('AngularCtrl', function ($scope) {
     $scope.workdata = that.workdata;
  });


  this.initializeWebsocket = function() {
      this.webSocket = new WebSocket('ws://url2ws');
      this.webSocket.onmessage = function(resp) {
        that.workdata = JSON.parse( resp.data );
        $('#wait').hide();
      }

}

var app = null;

$( 'document' ).ready(function() {
    $('#wait').show();
    app = new WebApp();
    app.initializeWebsocket();
  });

And this is my HTML:

    <!doctype html>
<html class="no-js" ng-app="AngularApp">
<head>
 <script src="js/vendor/jquery.js"></script>
 <script src="js/app.js"></script>
  <script src="js/angular.min.js"></script>
</head>
<body ng-controller="AngularCtrl">
Field1 : {{workdata.field1}}<br />
Field2 : {{workdata.field2}}
</body>
</html>

At first Field1 and Field2 is empty. But when the Websocket is receiving data, the received data in resp is correct and workdata is also filled correctly. But nothing changes on website. Maybe you can help me to correct my code.

EDIT I have complemented my javascriptcoding with the call of $scope.$apply() but it has no effect:

   function WebApp() {
  this.webSocket = null;
  this.workdata = null;
  this.$scope = null;

  var that = this;


  this.AngularApp = angular.module('AngularApp', []);
  this.AngularApp.controller('AngularCtrl', function ($scope) {
    $scope.workdata = that.workdata; 
    that.$scope= $scope;
  });


  this.initializeWebsocket = function() {
      this.webSocket = new WebSocket('ws://url2ws');
      this.webSocket.onmessage = function(resp) {
        that.workdata = JSON.parse( resp.data );
        that.$scope.$apply();
      }

}

var app = null;

$( 'document' ).ready(function() {
    $('#wait').show();
    app = new WebApp();
    app.initializeWebsocket();
  });
user1829716
  • 307
  • 1
  • 9
  • 20

1 Answers1

3

The variable is only filled in at the moment the controller is created, in the line $scope.workdata = that.workdata;. Modifying that.workdata afterwards, will not update $scope.workdata, so the watch {{workdata.field1}} will still display the original value.

To solve this, modify the scope's value and make sure to call $scope.$apply whenever you are modifying the scope outside of AngularJS's structures. The WebSocket callback is not handled by AngularJS so you have to call $scope.$apply to notify AngularJS to retrigger its cycle.

In addition, I would highly recommend to code your application in AngularJS structures, instead of using AngularJS as a library as you are doing now. See this excellent answer in that regard.

Community
  • 1
  • 1
Steve Klösters
  • 9,427
  • 2
  • 42
  • 53
  • Hi thank you for your reply, I'm note sure what you mean with $scope.$apply, because scopre is just a parameter in the anonymous function. I cannot find it of a member of controller or app. – user1829716 Oct 19 '15 at 12:25
  • That's why I recommended to use AngularJS structures. The WebSockets code you've written is outside of AngularJS, so AngularJS can not know when to run its updates. `$scope.$apply` is the way to let AngularJS know when something in its system has changed from outside its system. – Steve Klösters Oct 19 '15 at 14:40
  • hmm can you show me an example how to call $scope.$apply(). I've tried to save $scope as a member of my class in the binding function of the controller. After processing websockets data i tried to call that.$scope.$apply(). This results in no error but does not have any effect. (I have complemented the questions) – user1829716 Oct 19 '15 at 14:48