This was simply a mix up of variable name, while IBM was using pollId
in their route for getting a poll I was using id
but had managed to use pollId
in my controller, once I changed this all behaved as expected.
Why is my socket.io emit not causing a refresh of content
-
01-07-2023 - |
Question
I have been adapting the IBM angularjs tutorial here into a Yeoman angular-fullstack tutorial and it has been relatively easy except I have one Issue. When I vote on a Poll the data does not refresh and show the results on my version.
I have tried Debugging through it as best I can and I cannot see any difference between my version and the IBM version that would cause this issue. I have also looked here on SO and on google but I'm actually completely lost.
my entire code base is located here on github and I have embeded what I think is the relevant code below, Any help would be greatly appreciated
This is the client side controller
.controller('PollViewCtrl', function ($scope, $routeParams, Poll, socket){
$scope.poll = Poll.get({pollId: $routeParams.id});
socket.on('myvote', function(data) {
console.dir(data);
if(data._id === $routeParams.pollId) {
$scope.poll = data;
}
});
socket.on('vote', function(data) {
console.dir(data);
if(data._id === $routeParams.pollId) {
$scope.poll.choices = data.choices;
$scope.poll.totalVotes = data.totalVotes;
}
});
$scope.vote = function() {
var pollId = $scope.poll._id,
choiceId = $scope.poll.userVote;
if(choiceId) {
var voteObj = { poll_id: pollId, choice: choiceId };
socket.emit('send:vote', voteObj);
} else {
alert('You must select an option to vote for');
}
};
})
and this is the relavent server side code
//app.js
var io = require('socket.io').listen(app.listen(config.port));
var poll = require('./lib/controllers/polls');
io.sockets.on('connection', poll.vote);
//poll.js
exports.vote = function(socket) {
socket.on('send:vote', function(data) {
var ip = socket.handshake.headers['x-forwarded-for'] || socket.handshake.address.address;
Poll.findById(data.poll_id, function(err, poll) {
var choice = poll.choices.id(data.choice);
choice.votes.push({ ip: ip });
poll.save(function(err, doc) {
var theDoc = {
question: doc.question, _id: doc._id, choices: doc.choices,
userVoted: false, totalVotes: 0
};
for(var i = 0, ln = doc.choices.length; i < ln; i++) {
var choice = doc.choices[i];
for(var j = 0, jLn = choice.votes.length; j < jLn; j++) {
var vote = choice.votes[j];
theDoc.totalVotes++;
theDoc.ip = ip;
if(vote.ip === ip) {
theDoc.userVoted = true;
theDoc.userChoice = { _id: choice._id, text: choice.text };
}
}
}
socket.emit('myvote', theDoc);
socket.broadcast.emit('vote', theDoc);
});
});
});
};
Update
Here is the factory for socket
.factory('socket', function($rootScope) {
var socket = io.connect();
return {
on: function (eventName, callback) {
socket.on(eventName, function () {
var args = arguments;
$rootScope.$apply(function () {
callback.apply(socket, args);
});
});
},
emit: function (eventName, data, callback) {
socket.emit(eventName, data, function () {
var args = arguments;
$rootScope.$apply(function () {
if (callback) {
callback.apply(socket, args);
}
});
})
}
};
});;
Solution 2
OTHER TIPS
You have to make an apply when you're receiving the sockent on AngularJS because socket.io is not "in the AngularJS world".
You have a rerally great tutorial here to do what you want : http://www.html5rocks.com/en/tutorials/frameworks/angular-websockets/?redirect_from_locale=fr
If you have any questions just ask it !
Hope it helps