2011-08-05 38 views
5

我正在尝试将knockout JS添加到我们网站上的搜索页面。目前,您打开了一个jQuery对话框,其中有许多可供选择的条件复选框。如何使用撤消创建可观察数组?

有多个对话框有多种标准。当你打开对话框时,复选框在你点击“更新”按钮后才会生效,如果你点击取消或关闭窗口,你所做的改变被恢复并且对话框被设置为以前的状态。

我读了this和其他一些帖子。但是,这似乎只适用于ko.observable,我似乎无法让它与ko.observableArray一起使用。

有没有人完成过这个或有任何想法?

什么,我想要做的一个例子:

HTML:

<form> 
    <div> 
     <div> 
      <label><input type="checkbox" data-bind="checked: genders" value="1" />Male</label> 
      <label><input type="checkbox" data-bind="checked: genders" value="2" />Female</label> 
     </div> 
    </div> 
    <a id="buttonCancel">Cancel</a> 
    <a id="buttonUpdate">Update</a> 
</form> 
<div data-bind="text: ko.toJSON(viewModel)"></div> 

的Javascript:

var viewModel = { 
    genders: ko.observableArrayWithUndo([]) 
}; 

ko.applyBindings(viewModel); 

$('#buttonCancel').click(function(){ 
    viewModel.genders.resetChange(); 
}); 

$('#buttonUpdate').click(function(){ 
    viewModel.genders.commit(); 
    return false; 
}); 

回答

6

这里将接近它的一种方法:

//wrapper to an observableArray of primitive types that has commit/reset 
ko.observableArrayWithUndo = function(initialArray) { 
    var _tempValue = ko.observableArray(initialArray.slice(0)), 
     result = ko.observableArray(initialArray); 

    //expose temp value for binding 
    result.temp = _tempValue; 

    //commit temp value 
    result.commit = function() { 
     result(_tempValue.slice(0)); 
    }; 

    //reset temp value 
    result.reset = function() { 
     _tempValue(result.slice(0)); 
    }; 

    return result; 
}; 

你会绑定你的复选框yourName.temp和你的用户界面的其他部分只是你的名字。

下面是一个示例:http://jsfiddle.net/rniemeyer/YrfyW/

切片(0)是获得的阵列的浅拷贝单程(或甚至只是切片())。否则,你将在对同一个数组的引用上执行操作。

+0

感谢您的快速回答!让我看看它是如何运作的。 –

3

由于HTML类似:

<div> 
    <button data-bind="click: function() { undo(); }">Undo</button> 
    <input data-bind="value: firstName" /> 
    <input data-bind="value: lastName" /> 
    <textarea data-bind="value: text"></textarea> 
</div> 

您可以使用类似这样的一些淘汰赛的代码,基本上保存在撤消堆栈为每次更改后状态的JSON字符串表示。基本上你可以创建一个假依赖的observable来订阅视图中的所有属性,或者你可以手动迭代和订阅每个属性。

//current state would probably come from the server, hard coded here for example 
var currentState = JSON.stringify({ 
    firstName: 'Paul', 
    lastName: 'Tyng', 
    text: 'Text' 
}) 
    , undoStack = [] //this represents all the previous states of the data in JSON format 
    , performingUndo = false //flag indicating in the middle of an undo, to skip pushing to undoStack when resetting properties 
    , viewModel = ko.mapping.fromJSON(currentState); //enriching of state with observables 


//this creates a dependent observable subscribed to all observables 
//in the view (toJS is just a shorthand to traverse all the properties) 
//the dependent observable is then subscribed to for pushing state history 
ko.dependentObservable(function() { 
    ko.toJS(viewModel); //subscribe to all properties  
}, viewModel).subscribe(function() { 
    if(!performingUndo) { 
    undoStack.push(currentState); 
    currentState = ko.mapping.toJSON(viewModel); 
} 
}); 

//pops state history from undoStack, if its the first entry, just retrieve it 
    window.undo = function() { 
     performingUndo = true; 
     if(undoStack.length > 1) 
     { 
      currentState = undoStack.pop(); 
      ko.mapping.fromJSON(currentState, {}, viewModel); 
     } 
     else { 
      currentState = undoStack[0]; 
      ko.mapping.fromJSON(undoStack[0], {}, viewModel); 
     } 
     performingUndo = false; 
}; 

ko.applyBindings(viewModel); 

我有N个级别的样本撤消通过淘汰赛的位置:

http://jsfiddle.net/paultyng/TmvCs/22/

您可以为您的用途相适应。