I have a button that moves an item one position left in an observableArray. I am doing it the following way. However, the drawback is that categories()[index] gets removed from the array, thus discarding whatever DOM manipulation (by jQuery validation in my case) on that node.
Is there a way to swap two items without using a temporary variable so as to preserve the DOM node?
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");
}
I had a similar problem as I wanted jQuery drag & drop on my items. My solution became to use knockoutjs templates to bind the beforeRemove and afterAdd events to the model. The Person Class/function is also a simple knockout view model.
In the below example I use .draggable(), but you could easily use validation. Add your own code for manipulating the observableArray and you should be good to go.
HTML:
ViewModel:
I know this answer comes a bit late, but I thought it might be useful to others who want a more general swap solution. You can add a swap function to your observableArrays like so:
You can then use this function to swap two elements in an array given their indices:
For a moveUp function, you could then do something like this:
Here's my version of
moveUp
that does the swap in one step:That still doesn't solve the problem, though, because Knockout will still see the swap as a delete and add action. There's an open issue for Knockout to support moving items, though. Update: As of version 2.2.0, Knockout does recognize moved items and the
foreach
binding won't re-render them.thanks to Michael Best for his version of moveup
my version of moveDown