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();
  });

1 Answer 1

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.

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

3 Comments

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.
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.
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)

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.