0

My goal is to use websockets to receive someJSON` through and update a table in a directive.

I've created a simple directive :-

app.directive("penaltyTable", function() {
return {
    restrict: 'E',
    templateUrl: '/Content/AngularPartials/Coach/PenaltyLine.html',
    controller: function() {
        this.players = [];
        var penaltyController = this;

        var uri = "ws://localhost.local/api/CoachesTracker/10";

        //Initialize socket
        var websocket = new WebSocket(uri);

        // Error handling stuff here.....

        //Socket message handler
        websocket.onmessage = function (event) {
            var data = JSON.parse(event.data);
            penaltyController.players = data;
        };
    },
    controllerAs: 'penaltyTrackerCtrl'
};
});

I've created a simple template PenaltyLine.html

<table class="penalty-table">
    <tr ng-repeat-start="player in penaltyTrackerCtrl.players">
        <td>{{player.Number}}</td>
    </tr>
    <tr ng-repeat-end>
        <td>{{player.Name}}</td>
    </tr>
<table>

My web-socket receives data OK from the server, appears to update the players array however the template is never updated to display new data.

I think I am learning to run before I can walk with angular! Is there something basic I'm missing?

1 Answer 1

3

You need to trigger a digest. A safe way of doing this is using $timeout with a 0-time delay. You can also call the code in $scope.$apply (checking that a digest is not already running). $timeout, while ugly, is generally preferred.

app.directive("penaltyTable", function($timeout) {
return {
    restrict: 'E',
    templateUrl: '/Content/AngularPartials/Coach/PenaltyLine.html',
    controller: function() {
        this.players = [];
        var penaltyController = this;

        var uri = "ws://localhost.local/api/CoachesTracker/10";

        //Initialize socket
        var websocket = new WebSocket(uri);

        // Error handling stuff here.....

        //Socket message handler
        websocket.onmessage = function (event) {
            $timeout(function() {
                var data = JSON.parse(event.data);
                penaltyController.players = data;
            });
        };
    },
    controllerAs: 'penaltyTrackerCtrl'
};
});

The reason is that AngularJS doesn't know that your websocket just got a message, and hence doesn't know that anything happened in the "Angular" way of data binding and watchers etc. Maybe, coincidentally, something happened in your application to trigger a digest at just that moment and you don't see the issue, but most of the time you will.

A 'better' solution might be to write a wrapper around websocket that calls $rootScope.$digest after whatever callback you have there runs. If you aren't doing it too much then it's probably fine to go like this though.

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

2 Comments

Thanks, I've not quite progressed into wrappers yet, so would need to figure out what $rootScope and $digest are. Soon though!
Oh by wrapper I meant some kind of service where you register the websocket with callbacks, and make sure $rootScope.$digest gets called after. There should be good articles about those two, but the short of it is $rootScope is the highest $scope in your application, and $digest tells angular to check all the bindings, and if the variables have changed, update views etc.

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.