In my Knockout viewmodel, I've got some properties where I'm trying to make a hash observable. So instead of my pre-Knockout code of
self.MyHash = {};
I am now using:
self.MyHash = ko.observable({});
In other parts of my code, I am manipulating the hash with statements like these:
// add an entry
self.MyHash()["test"] = "My Value";
// remove an entry
delete self.MyHash()["test"];
The code works, in that the entries are added and removed properly. However, the changes to the hashtable don't seem to be detected by areas of the code that are observing it. For example, this puted observable never runs when I am changing the hashtable:
self.Querystring = koputed(function ()
{
var f = [];
$.each(self.MyHash(), function (k, v)
{
f.push(encodeURIComponent(k) + '=' + encodeURIComponent(v));
});
return (f.length > 0) ? f.join("&") : "";
});
I am going to guess that this is because Knockout observables are required to be simple variables (or observableArrays), and that it's not detecting the underlying changes to my hashtable.
If so, are there other options? Why isn't there an observableHash type in Knockout?
For what it's worth, my workaround is to have an observableArray of keys, and a regular JavaScript hashtable to lookup the values. Then I changed my puted method to observe the array of keys rather than the other hashtable variable I had before. I just want to make sure I'm not missing "The Right Way" to do it in Knockout.
self.MyHashKeys = ko.observableArray();
self.MyHash = {};
self.Querystring = koputed(function ()
{
var f = [];
$.each(self.MyHashKeys(), function (index, value)
{
f.push(encodeURIComponent(value) + '=' + encodeURIComponent(self.MyHash[value]));
});
return (f.length > 0) ? f.join("&") : "";
});
In my Knockout viewmodel, I've got some properties where I'm trying to make a hash observable. So instead of my pre-Knockout code of
self.MyHash = {};
I am now using:
self.MyHash = ko.observable({});
In other parts of my code, I am manipulating the hash with statements like these:
// add an entry
self.MyHash()["test"] = "My Value";
// remove an entry
delete self.MyHash()["test"];
The code works, in that the entries are added and removed properly. However, the changes to the hashtable don't seem to be detected by areas of the code that are observing it. For example, this puted observable never runs when I am changing the hashtable:
self.Querystring = ko.puted(function ()
{
var f = [];
$.each(self.MyHash(), function (k, v)
{
f.push(encodeURIComponent(k) + '=' + encodeURIComponent(v));
});
return (f.length > 0) ? f.join("&") : "";
});
I am going to guess that this is because Knockout observables are required to be simple variables (or observableArrays), and that it's not detecting the underlying changes to my hashtable.
If so, are there other options? Why isn't there an observableHash type in Knockout?
For what it's worth, my workaround is to have an observableArray of keys, and a regular JavaScript hashtable to lookup the values. Then I changed my puted method to observe the array of keys rather than the other hashtable variable I had before. I just want to make sure I'm not missing "The Right Way" to do it in Knockout.
self.MyHashKeys = ko.observableArray();
self.MyHash = {};
self.Querystring = ko.puted(function ()
{
var f = [];
$.each(self.MyHashKeys(), function (index, value)
{
f.push(encodeURIComponent(value) + '=' + encodeURIComponent(self.MyHash[value]));
});
return (f.length > 0) ? f.join("&") : "";
});
Share
Improve this question
edited Apr 10, 2012 at 12:58
Paul Tyng
7,5841 gold badge35 silver badges57 bronze badges
asked Apr 10, 2012 at 0:44
Mason G. ZhwitiMason G. Zhwiti
6,54012 gold badges64 silver badges99 bronze badges
1 Answer
Reset to default 7See the second example on the observable array page. Just make an array of key/value pairs:
// This observable array initially contains three objects
var anotherObservableArray = ko.observableArray([
{ name: "Bungle", type: "Bear" },
{ name: "George", type: "Hippo" },
{ name: "Zippy", type: "Unknown" }
]);
In your examples you are only iterating (except for deletion), so there is no real need to use an actual dictionary. It would be easy enough to just search for the key. I think the use of map is kind of a premature optimization to some extent. Its also not entirely in line with the ability of query strings to support the same key multiple times.
Edit: if you want to observe the key or value changing in this example, you would also have to make those properties observable:
var anotherObservableArray = ko.observableArray([
{ name: ko.observable("Bungle"), type: ko.observable("Bear") }
]);