KnockoutJS Sortable - 如何在afterMove arg上获取目标数据(单个observableArray)

时间:2014-05-23 08:27:43

标签: knockout.js knockout-2.0 knockout-sortable

HTML:

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

视图模型:

//...

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... 
}

我想做的是:

  • tasks2 移至 tasks1 的位置时,任务2 优先级将变为1任务1优先级将变为2 (换乘)。

我尝试了什么:

我在这里阅读了文档:https://github.com/rniemeyer/knockout-sortable

执行afterMove函数时收到一些对象,例如:

  • arg.item - 正在移动的实际项目
  • arg.sourceParent - 原始的observableArray
  • arg.targetParent - 目标observableArray

问题是:

目前我只对单个observableArray使用排序。

因此,我可以使用 arg.item 来更改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
}

但是,如何更改目标项目优先级?

arg.sourceParent arg.targetParent 现在返回相同的原始observableArray,因此我无法获取目标项来更改其优先级。< / p>

我希望我可以拥有arg.targetItem,所以我可以像这样更改目标项目优先级:

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
}

编辑:这是http://jsfiddle.net/L7BBz/

2 个答案:

答案 0 :(得分:3)

我之前遇到过类似的问题。这是我可以参考的POC,这也解决了嵌套级别任务的拖放和优先级。

这个POC显然需要一些调整和重新分解,但我相信这对你来说是最好的。

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

我使用了由Ryan Neimeyer编写的withIndex observable订阅函数。

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;
};

这通过任务的索引/优先级重复并重置它们。到目前为止,我发现这是最好的解决方案..

答案 1 :(得分:0)

这是Rahul发布的代码的重构。为了清晰起见,我重命名了一些变量,添加了一些注释,并删除了一些未使用的参数。

ko.observableArray.fn.withIndex = function (propertyName) {
    //by default use an "index" as our observable property. 
    propertyName = propertyName || "index";

    //whenever the array changes, make a single pass through to update the indexes
    this.subscribe(updatedArray => {
        var currentItem;

        for (var i = 0, upperBound = updatedArray.length; i < upperBound; i++) {
            currentItem = updatedArray[i]; //get the item

            //create the observable if it does not exist
            if (!currentItem[propertyName]) {
                currentItem[propertyName] = ko.observable();
            }

            currentItem[propertyName](i); //update the sequence
        }
    }, this);

    return this;
};

希望有人觉得有用。原版花了我一分钟才弄明白,我可以说一个非常聪明的人会尽快抨击它。