2011-08-05 47 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/

您可以爲您的用途相適應。

相關問題