I'm trying to wrap a cookie in a computed observable (which I'll later turn into a protectedObservable) and I'm having some problems with the computed observable. I was under the opinion that changes to the computed observable would be broadcast to any UI elements that have been bound to it.
I've created the following fiddle
JavaScript:
var viewModel = {};
// simulating a cookie store, this part isnt as important
var cookie = function () {
// simulating a value stored in cookies
var privateZipcode = "12345";
return {
'write' : function (val) { privateZipcode = val; },
'read': function () { return privateZipcode; }
}
}();
viewModel.zipcode = ko.computed({
read: function () {
return cookie.read();
},
write: function (value) {
cookie.write(value);
},
owner: viewModel
});
ko.applyBindings(viewModel);?
HTML:
zipcode:
<input type='text' data-bind="value: zipcode"> <br />
zipcode:
<span data-bind="text: zipcode"></span>?
I'm not using an observable to store privateZipcode
since that's really just going to be in a cookie. I'm hoping that the ko.computed
will provide the notifications and binding functionality that I need, though most of the examples I've seen with ko.computed
end up using a ko.observable
underneath the covers.
Shouldn't the act of writing the value to my computed observable signal the UI elements that are bound to its value? Shouldn't these just update?
Workaround
I've got a simple workaround where I just use a ko.observable
along side of my cookie store and using that will trigger the required updates to my DOM elements but this seems completely unnecessary, unless ko.computed
lacks the signaling / dependency type functionality that ko.observable
has.
My workaround fiddle, you'll notice that the only thing that changes is that I added a seperateObservable
that isn't used as a store, its only purpose is to signal to the UI that the underlying data has changed.
// simulating a cookie store, this part isnt as important
var cookie = function () {
// simulating a value stored in cookies
var privateZipcode = "12345";
// extra observable that isnt really used as a store, just to trigger updates to the UI
var seperateObservable = ko.observable(privateZipcode);
return {
'write' : function (val) {
privateZipcode = val;
seperateObservable(val);
},
'read': function () {
seperateObservable();
return privateZipcode;
}
}
}();
This makes sense and works as I'd expect because viewModel.zipcode
depends on seperateObservable
and updates to that should (and does) signal the UI to update. What I don't understand, is why doesn't a call to the write
function on my ko.computed
signal the UI to update, since that element is bound to that ko.computed
?
I suspected that I might have to use something in knockout to manually signal that my ko.computed
has been updated, and I'm fine with that, that makes sense. I just haven't been able to find a way to accomplish that.
$.cookie.get()
and$.cookie.set()
, simulated viacookie
in my example. I don't have the ability to make that an observable, aside from what i'm trying to do in myko.computed
observable itself. The idea is thatko.computed
would encapsulate the writing to / reading from the cookie, which is why I'm not a big fan of usingsubscribe
. – Faizabad