Neekoy
Neekoy

Reputation: 2533

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.

Upvotes: 1

Views: 395

Answers (1)

majidarif
majidarif

Reputation: 19985

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 is: to bind it's 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 want angular to update the view when the content gets updated, you'll have to call it manually. Angular doesn't know if the content got updated because there was no interaction with 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();
});

Upvotes: 1

Related Questions