I found the solution how to use the observable array as dictionary on http://jsfiddle.net/karlhorky/D4D3f/
ko.observableArray.fn.indexBy = function (keyName) {
var index = ko.computed(function () {
var list = this() || [];
var keys = {};
ko.utils.arrayForEach(list, function (v) {
if (keyName) {
keys[v[keyName]] = v;
} else {
keys[v] = v;
}
});
return keys;
}, this);
this.findByKey = function(key) {
return index()[key];
};
return this;
};
I'd like to load data to dictionary using mapping plugin
this.Load = function () {
//this.items.
var mapping = {
'copy': ["Qid"]
};
ko.mapping.fromJS(data, mapping, this.items);
count = 0;
};
but can't search by key data loaded using mapping plugin
The mapping plugin turns regular properties into observable properties.
So in your indexBy
you need to handle the case when your keyName
refers to a ko.observable
.
When you get the key property value with v[keyName]
you need to use ko.utils.unwrapObservable
(or ko.unwrap
if you using a newer version of KO) to make sure to correctly unwrap your observable property:
ko.observableArray.fn.indexBy = function (keyName) {
var index = ko.computed(function () {
var list = this() || [];
var keys = {};
ko.utils.arrayForEach(list, function (v) {
if (keyName) {
keys[ko.utils.unwrapObservable(v[keyName])] = v;
} else {
keys[v] = v;
}
});
return keys;
}, this);
this.findByKey = function (key) {
return index()[key];
};
return this;
};
Demo JSFiddle.