var createItem = function (obj) {
// Up to you how you map to "viewmodels",
// If you want two-way binding (for editing),
// wrap in an observable.
// Example for 1-way binding
return Object.assign({
name: obj.name,
id: obj.id,
randomNr: Math.random()
}, Object.keys(obj.properties).reduce(function(res, key) {
res[key] = obj.properties[key];
return res;
}, {}));
};
var VM = function() {
this.rawData = ko.observableArray([]);
// Create "item" view models from the array of objects
this.items = ko.pureComputed(function() {
return this.rawData().map(createItem);
}, this);
// Store items by `id` prop. (Could also be a plain object)
var itemMap = ko.pureComputed(function() {
return new Map(
this.items().map(function(item) {
return [item.id, item];
})
);
}, this);
// Store the id of the selected item
this.selectedId = ko.observable(null);
// Whenever either the selected id, _or_ the array of items changes,
// update the selected item
this.selectedItem = ko.pureComputed(function() {
return itemMap().get(this.selectedId());
}, this);
};
VM.prototype.loadData = function(json) {
// Hardcoded
json = '[{"name":"A", "id":"A", "properties":{"description":"A", "text":"A", "number":"one"}}, {"name":"B", "id":"B", "properties":{"description":"B", "text":"B", "number":"two"}},{"name":"C", "id":"C", "properties":{"description":"C", "text":"C", "number":"three"}}]';
// Might want to wrap in a try catch
this.rawData(JSON.parse(json));
}
var vm = new VM();
ko.applyBindings(vm);
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<select data-bind="options: items,
optionsText: 'name',
optionsValue: 'id',
value: selectedId"></select>
<p>Your selection:<p>
<div data-bind="with: selectedItem">
<h3>Name: <span data-bind="text: name"></span></h3>
<h4>Description:<span data-bind="text: description + randomNr"></span></h4>
<p>Nr:<span data-bind="text: number"></span></p>
</div>
<button data-bind="click: loadData">load data</button>