私は同様の問題を解決しようとしているときにこの投稿に出くわし、次の人のために私のアプローチと解決策を投稿すると思いました。
私はあなたの考え方に沿って進みました-オブジェクトのクローンを作成し、「元に戻る」で古いデータを再入力します。
1)データオブジェクトを新しいページ変数( "_initData")にコピーします。2)元のサーバーオブジェクトからObservableを作成します。3)変更されていないデータ( "_initData")でオブザーバブルを「元に戻す」リロードします。
簡略化されたJS:var _viewModel; var _initData = {};
$(function () {
//on initial load
$.post("/loadMeUp", {}, function (data) {
$.extend(_initData , data);
_viewModel = ko.mapping.fromJS(data);
});
//to rollback changes
$("#undo").live("click", function (){
var data = {};
$.extend(data, _initData );
ko.mapping.fromJS(data, {}, _viewModel);
});
//when updating whole object from server
$("#updateFromServer).live("click", function(){
$.post("/loadMeUp", {}, function (data) {
$.extend(_initData , data);
ko.mapping.fromJS(data, {}, _viewModel);
});
});
//to just load a single item within the observable (for instance, nested objects)
$("#updateSpecificItemFromServer).live("click", function(){
$.post("/loadMeUpSpecificItem", {}, function (data) {
$.extend(_initData.SpecificItem, data);
ko.mapping.fromJS(data, {}, _viewModel.SpecificItem);
});
});
//updating subItems from both lists
$(".removeSpecificItem").live("click", function(){
//object id = "element_" + id
var id = this.id.split("_")[1];
$.post("/deleteSpecificItem", { itemID: id }, function(data){
//Table of items with the row elements id = "tr_" + id
$("#tr_" + id).remove();
$.each(_viewModel.SpecificItem.Members, function(index, value){
if(value.ID == id)
_viewModel.SpecificItem.Members.splice(index, 1);
});
$.each(_initData.SpecificItem.Members, function(index, value){
if(value.ID == id)
_initData.SpecificItem.Members.splice(index, 1);
});
});
});
});
個々のプロパティごとにハンドラーを追加したくないほど複雑なオブジェクトがありました。
オブジェクトにリアルタイムでいくつかの変更が加えられます。これらの変更は、observableと「_initData」の両方を編集します。
サーバーからデータを取得したら、「_ initData」オブジェクトを更新して、サーバーとの同期を維持しようとします。