knockout.jsknockout-2.0knockout-sortable

KnockoutJS Sortable - How to get target data on afterMove arg (single observableArray)


html:

<div class="grid" data-bind="sortable: { data: tasks, afterMove: sortingTasks }">
    // ...
</div>

viewmodel:

//...

tasks = ko.observableArray([
  {
     id       : 1,
     name     : "tasks1",
     priority : 1
  },
  { 
     id       : 2,
     name     : "tasks2",
     priority : 2
  }
]);

sortingTasks = function(arg)
{
    var currentIndex = (arg.sourceIndex+1);
    var targetIndex  = (arg.targetIndex+1);

    // here the problem... 
}

What I want to do is:

What I have try:

I have read documentation here: https://github.com/rniemeyer/knockout-sortable

There have a few object received when afterMove function is execute such as:

The problem is:

Currently I use sorting for a single observableArray only.

So, I can use arg.item to change source priority with targetIndex:

sortingTasks = function(arg)
{
    var currentIndex = (arg.sourceIndex+1);
    var targetIndex  = (arg.targetIndex+1);

    // here the problem... 

    arg.item.priority = targetIndex; // change source item priority
}

but, how can i change the target item priority ?

the arg.sourceParent and arg.targetParent right now return the same original observableArray, so i can't get the target item to change it priority.

I wish i could have like arg.targetItem, so i can change the target item priority like this:

sortingTasks = function(arg)
{
    var currentIndex = (arg.sourceIndex+1);
    var targetIndex  = (arg.targetIndex+1);

    // here the problem... 

    arg.item.priority = targetIndex; // change source item priority
    arg.targetItem.priority = currentIndex; // change target item priority
}

EDIT: here is the http://jsfiddle.net/L7BBz/


Solution

  • I've faced similar issue before. This is my POC you can refer to, this solves nested level task drag and drop and priority as well.

    This POC obviously needs some tweaking and re-factoring but I am sure this is best for you to get started.

    http://jsfiddle.net/rahulrulez/UUMqz/

    I have used withIndex observable subscribe function written by Ryan Neimeyer..

    ko.observableArray.fn.withIndex = function(prop) {
        //by default use an "index" observable
        prop = prop || "index";
    
        //whenever the array changes, make a single pass through to update the indexes
        this.subscribe(function(newValue) {
            var item;
            for (var i = 0, j = newValue.length; i < j; i++) {
                //create the observable if it does not exist
                item = newValue[i];
    
                if (!item[prop]) {
                    item[prop] = ko.observable();
                }
    
                item[prop](i);   
            }
        }, this);
    
        return this;
    };
    

    This reiterates through the indexes / priorities of tasks and reset them. I found this the best solution so far..