2012-04-21 49 views
20

我有一個按鈕,將一個項目移動到observableArray中的一個位置。我按照以下方式進行。然而,缺點是categories()[index]被從數組中刪除,因此放棄了該節點上的任何DOM操作(通過jQuery驗證)。如何交換observableArray中的兩個項目?

有沒有一種方法來交換兩個項目,而不使用一個臨時變量,以保存DOM節點?

moveUp: function (category) { 
     var categories = viewModel.categories; 
     var length = categories().length; 
     var index = categories.indexOf(category); 
     var insertIndex = (index + length - 1) % length; 

     categories.splice(index, 1); 
     categories.splice(insertIndex, 0, category); 
     $categories.trigger("create"); 
    } 

回答

36

這裏是我的moveUp版本,做掉一個步驟:

moveUp: function(category) { 
    var i = categories.indexOf(category); 
    if (i >= 1) { 
     var array = categories(); 
     categories.splice(i-1, 2, array[i], array[i-1]); 
    } 
} 

這仍然不能解決問題但是,因爲Knockout仍然會將交換視爲刪除和添加操作。不過,Knockout支持移動項目有open issue更新:從版本2.2.0開始,Knockout確實識別移動的項目,並且綁定不會重新呈現它們。

+0

非常感謝,這裏是** moveDown **示例http:// stackoverflow。com/a/22348385/287084 – Orhaan 2015-12-20 22:39:26

0

我有一個類似的問題,因爲我想jQuery的拖累我的項目&下降。 我的解決方案成爲使用knockoutjs模板將beforeRemove和afterAdd事件綁定到模型。 Person類/函數也是一個簡單的挖空視圖模型。

在下面的例子中,我使用.draggable(),但你可以很容易地使用驗證。添加你自己的代碼來操作observableArray,你應該很好去。

HTML:

<div data-bind="template: {foreach:attendeesToShow, beforeRemove:hideAttendee, afterAdd:showAttendee}"> 
    <div class="person"> 
     <img src="person.jpg" alt="" /> 
     <div data-bind="text: firstName" ></div> 
     <div class="deleteimg" data-bind="click:$parent.removeAttendee" title="Remove"></div> 
    </div> 
</div> 

視圖模型:

+0

可以詳細說明嗎?我試圖做的是使用按鈕來允許用戶排序​​(以後可能會實現拖放)。如何處理beforeRemove,afterAdd保留DOM元素? DOM元素是由Knockout生成的,但是通過jQuery驗證進行了更改,並且通過從重新插入項目中刪除而丟失更改。 – 2012-04-24 08:12:10

+0

在我的示例中,我簡單地重新添加可拖動項,在您的案例驗證中,項目重新添加到DOM時。在我的情況下,它不需要保存任何狀態變量(它們都在模型中),所以它適用於我。驗證不應該一樣嗎? – jornare 2012-04-24 08:28:49

0

感謝Michael Best爲他的版本的前移

我的版本下移

moveDown: function(category) { 
    var array = categories(); 
    var i = categories.indexOf(category); 
    if (i < arr.length) { 
     categories.splice(i, 2, array[i + 1], array[i]); 
    } 
} 
+0

您的版本無法正常工作。用「array.length - 1」代替「arr.length」就可以了。 – 2016-02-05 17:41:14

5

的,我知道這個答案來得有點晚了,但我想誰想要一個更一般的可能是有用的人交換解決方案您可以添加一個交換功能,以您的observableArrays像這樣:

ko.observableArray.fn.swap = function(index1, index2) { 
    this.valueWillMutate(); 

    var temp = this()[index1]; 
    this()[index1] = this()[index2]; 
    this()[index2] = temp; 

    this.valueHasMutated(); 
} 

然後,您可以使用此功能來交換兩個數組中的元素賦予其索引:

myArray.swap(index1, index2); 

對於爲moveUp功能,你可以然後做這樣的事情:

moveUp: function(category) { 
    var i = categories.indexOf(category); 
    if (i > 0) { 
     categories.swap(i, i+1); 
    } 
}