使用Knockout JS重新排序列表中的项目

时间:2015-11-15 04:21:34

标签: javascript sorting knockout.js

我有一个可观察的项目数组。 '项目的一个属性'是' position',表示项目在列表中的位置。我希望能够通过下拉每个项目旁边的位置来重新排序页面上的项目。当用户在下拉列表中选择项目的位置时,将重新计算受影响的任何项目的位置值。

我遇到的问题是当我尝试使用事件绑定进行下拉时 - 我无法找到一种方法来传递原始&我的重新定位的新职位'功能。

我确信这可以通过使用这个简单示例的数组索引来完成,但我试图看看是否可以避免这种情况。

JSFiddle:http://jsfiddle.net/4tqahpkg/3/

<div class='liveExample'>
<ul data-bind="foreach: orderedItems">
    <li>
        <div>   <span data-bind="text: name"> </span> has Position:
            <select id="pos" data-bind=" options: orderedItems,
                    optionsText: function(item) { return item.position   },
                    optionsValue: function(item){ return item.position   },
                    value: position,
                    event: { change: function () {reposition($data.name(), position()); } } "></select>
        </div>
    </li>
</ul>

var Item = function (name, position) {
    this.name = ko.observable(name);
    this.position = ko.observable(position);

}

var viewModel = function () {
    var self = this;

    this.items = [
    new Item("item Three", "3"),
    new Item("item One", "1"),
    new Item("item Two", "2"),
    new Item("item Five", "5"),
    new Item("item Four", "4"),
    new Item("item Six", "6")];


    self.orderedItems = ko.computed(function () {

        return ko.utils.arrayFilter(this.items, function (item) {
            return true;
        }).sort(function (a, b) {
            var value1 = "",
                value2 = "";
            value1 = a.position() ? a.position() : "";
            value2 = b.position() ? b.position() : "";
            return value1 == value2 ? 0 : (value1 < value2 ? -1 : 1);
        });
    });

    self.curName = ko.observable();

    self.curItem = ko.computed(function (name) {
        return ko.utils.arrayFilter(this.items, function (item) {
            return item.name() == self.curName();
        });
    });

    self.reposition = function (name, newPosition) {

        self.curName(name);
        origPosition = self.curItem()[0].position();

        if (origPosition < newPosition) {
            for (var x = 0; x < orderedItems.length; x++) {
                if (origPosition < newPosition && self.orderedItems()[x].position() >= origPosition && self.orderedItems()[x].position() < newPosition) {
                    self.orderedItems()[x].position(self.orderedItems()[x].position() - 1);
                }

                if (origPosition > newPosition && self.orderedItems()[x].position() >= newPosition && self.orderedItems()[x].position() < origPosition) {
                    self.orderedItems()[x].position(self.orderedItems()[x].position() + 1);
                }

                if (self.orderedItems().name() == name) {
                    self.orderedItems()[x].position(newPosition);
                }
            }
        }
    };


};

ko.applyBindings(viewModel);

1 个答案:

答案 0 :(得分:0)

您想要访问旧位置,但您尚未为其定义任何存储空间。每个项目都必须有一个oldPosition变量(我已经成为私有变量),并且在更新oldPosition之前调用position函数的reposition订阅。

我已经对您的设计进行了一些重新设计,我认为这有点令人费解。我还没有实施reposition,我想你想要转移其他项目&#39;这些职位不会有重复。

&#13;
&#13;
var viewModel = function() {
  var self = this;

  var Item = function(name, pos) {
    this.name = ko.observable(name);
    this.position = ko.observable(pos);
    var oldPosition = pos;
    this.position.subscribe(function(newValue) {
      self.reposition(this, oldPosition, newValue);
      oldPosition = newValue;
    }, this);
  };

  this.items = [
    new Item("item Three", "3"),
    new Item("item One", "1"),
    new Item("item Two", "2"),
    new Item("item Five", "5"),
    new Item("item Four", "4"),
    new Item("item Six", "6")
  ];


  self.orderedItems = ko.computed(function() {
    return ko.utils.arrayFilter(this.items, function(item) {
      return true;
    }).sort(function(a, b) {
      return a.position() - b.position();
    });
  });

  self.curName = ko.observable();

  self.reposition = function(item, oldPosition, newPosition) {
    console.debug("Reposition", item, oldPosition, newPosition);
  };

};

ko.applyBindings(viewModel);
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<div class='liveExample'>
  <ul data-bind="foreach: orderedItems">
    <li>
      <div>	<span data-bind="text: name"> </span> has Position:
        <select id="pos" data-bind=" options: orderedItems,
						optionsText: 'position',
						optionsValue: 'position',
						value: position "></select>
      </div>
    </li>
  </ul>
</div>
&#13;
&#13;
&#13;