Saturday, May 11, 2024
 Popular · Latest · Hot · Upcoming
86
rated 0 times [  91] [ 5]  / answers: 1 / hits: 18774  / 12 Years ago, wed, march 21, 2012, 12:00:00

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.


More From » knockout.js

 Answers
47

sigh, I found someone with my exact same problem




If dependentObservables don't notifySubscribers on write, why do they
even bother to do it on read? They get added to the observables list
and subscribed to, but then they never trigger on updates. So what is
the point of subscribing to them at all?




Ryan Niemeyer answers:




I think that for your scenario, dependentObservables may not be the
right tool for the job. dependentObservables are set up to detect
dependencies in the read function and re-evaluate/notify whenever any
of those dependencies change. In a writeable dependentObservable, the
write function is really just a place to intercept the write and allow
you to set any observables necessary, such that your read function
would return the proper value (write is typically the reverse of read
in most cases, unless you are transforming the value).



For your case, I would personally use an observable to represent the
value and then a manual subscription to that observable to update the
original value (the one that you may not have control over).



It would be like: http://jsfiddle.net/rniemeyer/Nn5TH/




So it looks like this fiddle would be a solution



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) {
console.log(updated cookie value with: + val);
privateZipcode = val;
},
'read': function () {
return privateZipcode;
}
}
}();

viewModel.zipcode = ko.observable(cookie.read());

// manually update the cookie when the observable changes
viewModel.zipcode.subscribe(function(newValue) {
cookie.write(newValue);
});

ko.applyBindings(viewModel);​


That makes sense and its somewhat simpler to use. Overall I'm not sure how great of an idea it is to treat a cookie as an observable since the server could edit it in an ajax request, etc.


[#86685] Tuesday, March 20, 2012, 12 Years  [reply] [flag answer]
Only authorized users can answer the question. Please sign in first, or register a free account.
triston

Total Points: 545
Total Questions: 88
Total Answers: 94

Location: Lebanon
Member since Sun, Aug 2, 2020
4 Years ago
;