Nika Javakhishvili
Nika Javakhishvili

Reputation: 462

knockout, signalr chat application bug

This is my main page :

<div class="content" data-bind="component: { name: route().page, params: route }"></div>

This is my page1 component :

ko.components.register("page1", { require: "Scripts/App/pages/page1/page1" });

I've observableArray in page1.js :

 self.messages = ko.observableArray();

When page1 loads first time it works correctly, i have the following method :

   chat.client.broadcastMessage = function (name, mes) {          
            self.messages.push(new messageSignature({ name: name, mes: mes }));         
        };

And when user add message, chat.client.broadcastMessage firing and ui updates corectly. But when user navigate to another page(component) and then back to page1, self.messages is empty array, but inside broadcastMessage , it has old messages, for example :

console.log(self.messages()); // empty array
chat.client.broadcastMessage = function (name, mes) {          
    self.messages.push(new messageSignature({ name: name, mes: mes }));
    console.log(self.messages()); // Array[4]
};

And ui doesn't update anymore. If user click again add message, broadcastMessage triggering but:

  console.log(self.messages()); // empty array
    chat.client.broadcastMessage = function (name, mes) {          
        self.messages.push(new messageSignature({ name: name, mes: mes }));
        console.log(self.messages()); // Array[5]
    };

Upvotes: 0

Views: 322

Answers (1)

Ian Yates
Ian Yates

Reputation: 1354

The chat.client.broadcastMessage is your signalR proxy object being configured, right?

That's global state. But your component paging in and out is not global state so it's getting a new observable array for messages when it's constructed the second time.

This doesn't seem to make sense when you first look at it, except that SignalR client-side handlers are not really configurable once it's made the server connection. So you're connecting to the server after your first creation of page 1 (and configuration of that client-side hadnler), but then once you've connected you can't set up a new client-side handler properly. So the old handler persists, with its reference to the old observable array.

Make your observable array global, or at least a property of your page's main view model. Then pass it through to your page 1 component as a parameter.

Alternatively use something like ko.postbox (a Knockout plugin) to post messages around your page so your SignalR client-side handler can post/broadcast a message and one or more of your components can subscribe to these messages

Upvotes: 1

Related Questions