app.controller('ctrl', function($scope){ var socket = io.connect(); this.messages = []; this.sendmessage = function(){ socket.emit('new message', this.input_message); this.input_message = ''; } socket.on('new message', function(data){ this.messages.push(data); }); });
i getting data emitted socket, when try push data messages
array, shows error cannot read property push of undefined
. wrong doing?
this not work because calling this
in socket scope (this.messages.push(data)
), not same controller scope. why this.messages
undefined
, because declared in controller function scope, not in socket callback function scope. in javascript, each function has it's own scope (except arrow functions).
suggestion
app.controller('ctrl', function($scope){ var ctrlcontext = this; var socket = io.connect(); //using keyword here means //it's in controller function scope. this.messages = []; this.sendmessage = function(){ socket.emit('new message', this.input_message); this.input_message = ''; } socket.on('new message', function(data){ //inside callback function have different //scope, means this.messages undefined. //but referencing controller function scope, //are able use messages property set //outer (controller function) scope. ctrlcontext.messages.push(data); //as stated, have call $scope.$apply //or else digest cycle not triggered. }); });
however, if use this
keyword inside socket callback function using function.prototype.bind method, allows set context of executing function.
example
var person = { name: 'john doe'; } //create function , bind context person var changename = function() { this.name = 'peter smith'; }.bind(person); console.log(person); // {name: 'john doe'} changename(person); console.log(person); // {name: 'peter smith'}
for solution like:
app.controller('ctrl', function($scope){ var socket = io.connect(); this.messages = []; var callback = function(data){ this.messages.push(data); }.bind(this); socket.on('new message', callback); });
Comments
Post a Comment