javascript - 在 ko.observableArray 模型绑定(bind)问题中向下移动项目

标签 javascript arrays knockout.js

编辑

显然逻辑是正确的。我怀疑问题在于我如何从 API 的 JSON 响应绑定(bind) View 模型。我添加了更多代码来尝试帮助诊断问题。

我是否正确绑定(bind)了 View 模型?

原帖

我不是问如何在 observableArray 中移动项目,我的代码是从这里在数组内上下移动项目: How do I swap two items in an observableArray?

晋升@Michael Best:https://stackoverflow.com/a/10630319/1888402

由@Moes向下移动:https://stackoverflow.com/a/26726556/1888402

我遇到的问题是将项目向下移动。上升得很好,问题似乎出在逻辑上。

JSON 模型

{
  "Options": {
    "SelectedHeader": "Left Header",
    "AvailableHeader": "Right Header"
  },
  "Selected": [
    {
      "Order": 2,
      "ID": 1,
      "Label": "Duration"
    },
    {
      "Order": 11,
      "ID": 5,
      "Label": "Metres / Min"
    },
    {
      "Order": 23,
      "ID": 7,
      "Label": "Sprint Dis/Min"
    },
    {
      "Order": 9,
      "ID": 15,
      "Label": "Max Velocity"
    },
    {
      "Order": 6,
      "ID": 16,
      "Label": "Hi Intensity Running"
    }
  ],
  "Available": [
    {
      "ID": 123,
      "Label": "I'm Available"
    }
  ],
  "WebServiceMethodUrl": "../../../Services/SomeAsmxService.asmx/SaveStuff"
}

查看模型

         function ViewModel(){
            var self = this;
            self.Options = model.Options
            self.Available = ko.observableArray(model.Available);
            self.Selected = ko.observableArray(model.Selected);
            self.WebServiceMethodUrl = model.WebServiceMethodUrl;
            self.addSelected = function(item){
                item.Order = self.Selected().length;
                self.Available.remove(item);
                self.Selected.push(item);
            };
            self.removeSelected = function(item){
                self.Available.push(item);
                self.Selected.remove(item);
            };
            self.moveUp = function(item) {
                var i = self.Selected.indexOf(item);
                if (i >= 1) {
                    var array = self.Selected();
                    self.Selected().splice(i-1, 2, array[i], array[i-1]); //Works fine
                    item.Order = i;
                }
            };
            self.moveDown = function(item) {
                var i = self.Selected.indexOf(item);
                if (i < self.Selected().length - 1) {
                    var array = self.Selected();
                    self.Selected().splice(i, 2, array[i + 1], array[i]);
                    item.Order = i;
                    self.Selected.valueHasMutated(); //Force rebind
                }
            };
            self.SaveIt = function(){
                postDataAsync(self.WebServiceMethodUrl, "{queryString: '"+ ko.toJSON(self) + "'}", "Could not save settings.", function (resp){});
            }
            self.sortedSelected = ko.computed(function(){
                return self.Selected().sort(function(left, right) { return left.Order == right.Order ? 0 : (left.Order < right.Order ? -1 : 1) });
            });
        }



        var vm = new ViewModel();

        ko.applyBindings(ViewModel);

HTML 和绑定(bind)

 <!-- ko if: sortedSelected().length -->
   <tbody data-bind="with:sortedSelected">
        <!-- ko foreach: Selected -->
            <!-- ko ifnot: (ID == 0) -->
                <tr>
                    <td class="order">

                        <p data-bind="click: moveUp, clickBubble: false"><i class="fa fa-arrow-up"></i></p>
                        <p data-bind="text: $index() + 1"></p>
                        <p data-bind="click: moveDown, clickBubble: false"><i class="fa fa-arrow-down move-down"></i></p>
                    </td>
                    <td data-bind="text:Label, attr: { id: ID }"></td>
                    <td><a class="remove" data-bind="click: removeSelected, clickBubble: false">Remove&nbsp;&nbsp;<i class="fa fa-arrow-circle-o-right"></i></a></td>
                </tr>
            <!-- /ko-->
        <!-- /ko-->
    </tbody>
    <!-- /ko -->

因此,如果我要对第 5 项调用 moveDown 函数,那么它应该变成第 6 项,而第 6 项应该变成第 5 项。不知道为什么这不起作用,因为这只是逻辑被颠倒了。

示例

JSFiddle

最佳答案

问题在于您的 sortedSeleted 计算。任何时候 Selected 被修改时,计算值都会被重新计算,因为它依赖于 Selected。当计算结果被评估时,它会对 Selected 进行排序。您可能没有意识到 sort 会修改它所调用的数组,同时也会返回该数组。这种按 Order 排序导致 moveUpmoveDown 函数显得不一致。

您很可能想要对Selected副本进行排序。正如 @RoyJ 指出的,您可以使用 slice 来获取数组的浅拷贝。

关于javascript - 在 ko.observableArray 模型绑定(bind)问题中向下移动项目,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33018440/

相关文章:

javascript - 在Javascript中按空格和新行分割字符串

javascript - 设置带有 knockout 的 select2 ajax 的初始值

javascript - knockout 可观察未渲染到屏幕

javascript - 如何使用 Direct store 在 Ext JS 中设置远程自动完成?

javascript - jQuery UI 模态确认对话框中取消按钮的名称有什么神奇之处吗?

java - 调用方法时出错

c - A[m][n]中的A不是指针吗(类比我们用指针定义二维矩阵)

javascript - KnockoutJS observableArray 在通知订阅者之前是否会区分新旧数组?

javascript - jquery tablesorter 类 sticky-false

c++ - 在 C++ 中将 float 的文本文件读入二维 vector