I need to detect when items are moved in an observableArray. In my current version (2.1.0) I accomplish this by calling setTimeout
on all delete events and waiting to see if an add event follows immediately on its heels:
var delayed = [];
var key; /* obtained by comparing original observableArray with updated list and iterating all differences */
if( /** record exists in original list but not new list ) {
// it was deleted, we don't immediately fire a notification (it may get re-inserted in a moment)
delayed[key] = setTimeout(function() { sendDeleteNotification(key); }, 0);
}
else if( /** record exists in new list but not original */ ) {
if( delayed[key] ) {
// it was deleted and immediately re-added (it's a move)
clearTimeout(delayed[key]);
sendMoveNotification( key );
}
else {
// it was added
sendAddedNotification( key );
}
}
In knockout 2.2, I see new events for beforeMove and afterMove. However, I can't find any means to utilize them programmatically.
The end goal is to be able to mirror client changes in the database immediately, but not show an add/delete in place of a move event. A record moved up or down in the list shouldn't be marked as deleted and then newly added.
Can the new beforeMove/afterMove bindings be utilized in JavaScript directly (e.g. event model?) to improve this?
Cheers,
The answer I utilized was based on this so question and this jsfiddle.
The
beforeMove
andafterMove
functions can be accessed by a simple subscription:However, it turns out this wasn't particularly useful as it returns all the elements in the array that change index. For instance, if I delete a record from the list, I get a moved event for every record after the deleted one.
So I'll be sticking with the timeout until I find something better.