Neil
Neil

Reputation: 2519

AngularJS: Best way to handle data from socket with ng-repeat

I am quite new to real-time data with Socket.IO. I am trying to figure out what is the best way to handle data coming in from Socket.IO in an AngularJS ng-repeat?

Right now I have the backend sending up the entire data structure every time there is an update to it.

But this is causing the ng-repeat to refresh in order to display the new data (if I make any modifications to the data on the client side only, they are removed next time data is sent from the backend). Is there a better way to do this?

Should I filter out the only data that requires updating on the backend and then send that to the front end instead of delivering the entire data structure again? (But then how would I apply this in an ng-repeat with only the update data...)

I tried using UnderscoreJS extend method in the frontend but it seems to cause issues with the sorting of data in ng-repeat (orderBy and filter both break).

My specific use case is dealing with sports scores (several games (objects) in an array), I am constantly getting updates on my data whether they are the time changing in a game, or a scoring play. Updates are happening pretty much every second. I am tapping into this specific API and grabbing all the data on a specific refresh variable, then sending it to the front-end via a socket. Not the ideal case to use sockets really, but it is the only way to interact with the API that I have discovered so far.

Upvotes: 1

Views: 2418

Answers (2)

Michael Benford
Michael Benford

Reputation: 14104

I think it's best if you send to the client new events only, not the entire list every time. You could add those events to an array and let ng-repeat render them. Here's an example using ngSocketIO, a simple SocketIO module I've created for Angular (the syntax won't be much different than the one you're already using, I guess):

app.controller('MyCtrl', function($scope, socket) {
    $scope.events = [];

    socket.on('someEvent', function(data) {
        $scope.events.push(data);
    }
}

And the markup could be something like this:

<ul>
  <li ng-repeat="event in events">{{ event.name }}</li>
</ul>

Now you can change any object of the events array and it won't be removed when the next event arrives. If the same event can be sent again (with new data, perhaps), then you could replace the array with a "hash":

app.controller('MyCtrl', function($scope, socket) {
    $scope.events = {};

    socket.on('someEvent', function(data) {
        $scope.events[data.id] = data;
    }
}

The ng-repeat expression needs to be slightly changed in order for it to iterate over a hash:

<li ng-repeat="(id, data) in events">{{id}}: {{data.name}}</li>

In this case any local changes to an event will be lost if the same event arrives again. If you want to partially update the local copy of if, you'll need to do it manually, perhaps by saving the parts you don't want to lose and restore them after updating the local event with the new data from the server.

Upvotes: 1

Related Questions