问题
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:
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]);
});
});
}]);
回答2:
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);
});
};
来源:https://stackoverflow.com/questions/28722737/angular-js-socket-io-event-updates-model-not-view