Neekoy Neekoy - 5 months ago 13
AngularJS Question

Socket.io emit event doesn't update Angular controlled element

I made a simplified example of the issue below. Basically the "this.content" variable doesn't get changed by the "socket.on" event (which is otherwise working properly).

index.html:

<div ng-controller="gameController as game">
<button ng-click="game.buttonClick()">This changes the text when clicked.</button>
<div>{{ game.content }}</div>
</div>


controller.app:

app.controller('gameController', function($scope, $http) {
this.content = "Default";

this.buttonClick = function() {
this.content = "Content changes to this, when the button is clicked.";
};

socket.on('gameFound', function () {
this.content = "Content doesn't change to this, when a message is emitted.";
console.log("This message is being logged into the console though.");
});
});


On the server-side, I have a socket.emit('gameFound', "Something"), which is working properly.

I think the issue is that "this.content" is referring to something else in the context of socket.on.

How can I change the value of "this.content" in the socket.on function?

Any help is appreciated.

Answer

I think the context is wrong, try:

app.controller('gameController', function($scope, $http) {
    var self = this;
    self.content = "Default";

    this.buttonClick = function() {
        self.content = "Content changes to this, when the button is clicked.";
    };

    socket.on('gameFound', function () {
        self.content = "Content doesn't change to this, when a message is emitted.";
        console.log("This message is being logged into the console though.");
    });
});

Doing this.content inside socket.on actually meant socket.content and not gameController.content as you expected.

Another approach would be to bind its context to the outside,

socket.on('gameFound', function () {
  this.content = "Content doesn't change to this, when a message is emitted.";
  console.log("This message is being logged into the console though.");
}.bind(this));

If you wan't angular to update your view when the content gets changed, you have to call it manually. Angular doesn't know there was a change because there was no interaction to the DOM. Try this instead:

socket.on('gameFound', function () {
    self.content = "Content doesn't change to this, when a message is emitted.";
    console.log("This message is being logged into the console though.");
    // update the view
    $scope.$apply();
});
Comments