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"); }
To swap two array elements with this method: Create a new array, containing both elements in a particular order. Use the JavaScript array destructing syntax to unpack the values from the array into a new array that contains both elements in a reversed order.
A far better method you can use to swap array elements is destructuring, as it does the job in only one line of code. You just create a new array containing both elements in a particular order, then assign it to a new array that contains both elements in the reversed order.
Here's my version of moveUp
that does the swap in one step:
moveUp: function(category) { var i = categories.indexOf(category); if (i >= 1) { var array = categories(); categories.splice(i-1, 2, array[i], array[i-1]); } }
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.
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:
ko.observableArray.fn.swap = function(index1, index2) { this.valueWillMutate(); var temp = this()[index1]; this()[index1] = this()[index2]; this()[index2] = temp; this.valueHasMutated(); }
You can then use this function to swap two elements in an array given their indices:
myArray.swap(index1, index2);
For a moveUp function, you could then do something like this:
moveUp: function(category) { var i = categories.indexOf(category); if (i > 0) { categories.swap(i, i+1); } }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With