var Item = function(data) { this.name = ko.observable(); this.price = ko.observable(); //populate our model with the initial data this.update(data); }; //can pass fresh data to this function at anytime to apply updates or revert to a prior version Item.prototype.update = function(data) { this.name(data.name || "new item"); this.price(data.price || 0); }; var ViewModel = function(items) { //turn the raw items into Item objects this.items = ko.observableArray(ko.utils.arrayMap(items, function(data) { return new Item(data); })); //hold the currently selected item this.selectedItem = ko.observable(); //make edits to a copy this.itemForEditing = ko.observable(); this.selectItem = this.selectItem.bind(this); this.acceptItem = this.acceptItem.bind(this); this.revertItem = this.revertItem.bind(this); }; ko.utils.extend(ViewModel.prototype, { //select an item and make a copy of it for editing selectItem: function(item) { this.selectedItem(item); this.itemForEditing(new Item(ko.toJS(item))); }, acceptItem: function(item) { var selected = this.selectedItem(), edited = ko.toJS(this.itemForEditing()); //clean copy of edited //apply updates from the edited item to the selected item selected.update(edited); //clear selected item this.selectedItem(null); this.itemForEditing(null); }, //just throw away the edited item and clear the selected observables revertItem: function() { this.selectedItem(null); this.itemForEditing(null); } }); ko.applyBindings(new ViewModel([ { name: "Cheese", price: 2.50 }, { name: "Pepperoni", price: 3.25 }, { name: "Deluxe", price: 4.25 } ]));
<ul data-bind="foreach: items"> <li> <a href="#" data-bind="click: $parent.selectItem, text: name"></a> (<span data-bind="text: price"></span>) </li> </ul> <hr/> <div data-bind="with: itemForEditing"> <form class="form-horizontal"> <div class="control-group"> <label class="control-label" for="itemName">Name</label> <div class="controls"> <input type="text" id="itemName" data-bind="value: name" /> </div> </div> <div class="control-group"> <label class="control-label" for="itemPrice">Price</label> <div class="controls"> <input type="number" step=".01" id="itemPrice" data-bind="value: price" /> </div> </div> <div class="control-group"> <div class="controls"> <button class="btn" data-bind="click: $parent.acceptItem">Accept</button> <button class="btn" data-bind="click: $parent.revertItem">Cancel</button> </div> </div> </form> </div>