0

I have sockets working, in that each client seems to be running the proper code block that console.logs the event. The client that sends the message updates the view, but the other connected clients don't.

But when another client sends a message, its view updates with all the backlogged messages that it's been pushing to the model, so I know that part is working. It's just the view that's not updating.

I've done some reading, and it looks like I need to refactor my code to use $scope and $scope.$apply, but I'm not sure how.

app.controller('StoryController', ['$http', '$scope', function($http, $scope){
    var story = this;

    socket.on('new storyPoint', function(msg){
        //console.log('new storyPoint!', msg);
        story.points.push(msg);
        $('.story').scrollTop($('.story')[0].scrollHeight);
        console.log('last story point:', story.points[story.points.length - 1]);
    });
}]);

As you can see, I'm not actually using $scope yet, and I'm pretty sure I need to, but trying to mimic other solutions to this problem has failed.

Edit: And here's the view:

<div class="container story-container" ng-controller="StoryController as storyCtrl">
<aside class="players" id="players"><h1>Players </h1>
    <input name="username" type="text" ng-model="storyCtrl.username"/>
    <ul class="players-list">
        <li>{{storyCtrl.username}}</li>
        <li ng-repeat="player in game.settings.players">{{player}}</li>
    </ul>
</aside>
<div class="main">
    <h1 class="story-title">{{game.settings.title}}</h1>
    <ul class="story">
        <li ng-repeat="storyPoint in storyCtrl.points"><p>{{storyPoint.body}}</p></li>
        <li><p>{{storyCtrl.point.body}}</p></li>
    </ul>
    <form name="storyForm" ng-submit="storyCtrl.addPoint(storyCtrl)">
        <textarea ng-model="storyCtrl.point.body" name="storyPoint" rows="5"></textarea>
        <input class="btn btn-success" type="submit"/>
    </form>
</div>

1
  • can you show us your view binding ? Commented Feb 25, 2015 at 15:22

2 Answers 2

3

The issue is that Socket.io does not live inside the angular lifecycle, and thus Angular doesn't know new data has come in. You're right that you need to inject $scope into your controller, and the perform a $scope.$apply() inside your socket.io callback, as the last action.

$scope.$apply() lets angular know that data has updated, and to refresh what needs to be refreshed.

app.controller('StoryController', ['$http', '$scope', function($http, $scope){
    var story = this;

    socket.on('new storyPoint', function(msg){
        //console.log('new storyPoint!', msg);            
        $scope.$apply(function(){
            story.points.push(msg);
            $('.story').scrollTop($('.story')[0].scrollHeight);
            console.log('last story point:', story.points[story.points.length - 1]);             
        });
    });
}]);
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks, I could have sworn I tried this, but it wasn't working for some reason. I think it needs to be $scope.$apply();
0

Following code work for me, Whenever you get message from socket you just need to bind your code inside $scope.$apply() function

 socket.onmessage = function (e) {

            $scope.$apply(function () {
                $scope.onMessge(e);
            });

        };

Comments

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.