按多个参数对oberservableArray进行排序

时间:2015-06-08 20:41:39

标签: javascript jquery sorting knockout.js

我正在尝试按obervableArray的两项进行排序。我在http://jsfiddle.net/organa7/yyy3y2ka/创建了一个简化版本。

Line Group Id
<select data-bind="options: lineGroupIds, optionsValue: 'value', optionsText: 'text', value: selectedGroupId">
</select>

Line Type
<select data-bind="options: lineTypes, optionsValue: 'value', optionsText: 'text', value: selectedLineType">
</select>

<button data-bind="click: addLine">Add Line</button>
</br>
Line Count:&nbsp;<span data-bind="text: lines().length"></span>
</br>
<table> 
     <thead>
         <tr>
             <th>Line Group Id</th>
             <th>Line Type</th>
         </tr>
     </thead>
<tbody data-bind='foreach: linesSorted'>
    <tr>
         <td>
            <span data-bind="text: lineGroupId"></span>
        </td>
        <td>
            <span data-bind="text: lineType"></span>
        </td>
    </tr>
</tbody>
</table>
function myViewModel() {
    var self = this;

    self.selectedLineType = ko.observable(2);
    self.selectedGroupId = ko.observable(2);

    self.lines = ko.observableArray([
        {lineType: 1, lineGroupId: 1}, 
        {lineType: 1, lineGroupId: 2}, 
        {lineType: 1, lineGroupId: 3},

        /*{lineType: 2, lineGroupId: 1}, 
        {lineType: 3, lineGroupId: 1}, 
        {lineType: 2, lineGroupId: 1}, 
        {lineType: 2, lineGroupId: 2}, 
        {lineType: 3, lineGroupId: 2}, 
        {lineType: 2, lineGroupId: 1},*/
    ]);

    self.linesSorted = ko.pureComputed(function () {
        return self.lines().sort(function (a, b) {
            return a.lineType == b.lineType ?
            0 :
            (a.lineType < b.lineType ? -1 : 1);
        }).sort(function (a, b) {
            return a.lineGroupId == b.lineGroupId ?
            0 :
            (a.lineGroupId < b.lineGroupId ? -1 : 1);
        })
    });    

    self.lineTypes = ko.observableArray([
        {value: 2, text: "2"},
        {value: 3, text: "3"}
    ]);

    self.lineGroupIds = ko.observableArray([
        {value: 1, text: "1"},
        {value: 2, text: "2"},
        {value: 3, text: "3"}
    ]);

    self.addLine = function () {
        self.lines.push({
            lineType: self.selectedLineType(),
            lineGroupId: self.selectedGroupId()
        });
    };
}

ko.applyBindings(new myViewModel());

应按LineGroupId排序,然后按LineType排序。对于每个LineGroupId,应该只有一个LineType 1.这是父项。我已经为绑定到表的行添加了多种排序。它的工作正常,直到行数超过10:然后你得到的lineType为2或3,高于lineType为1.任何有关这里发生的事情的帮助将不胜感激。

2 个答案:

答案 0 :(得分:2)

你的排序方式不是你想要的。

  • 您似乎想要的内容:首先按行类型排序, 然后按 行组ID。
  • 您实际上在做什么:按行类型排序,然后按行组ID对结果再次 进行排序。

以下是排序功能的更新版本:

{{1}}

请参阅this jsfiddle了解演示。

PS。我建议为这种逻辑编写单元测试。请参阅CodeReview.SE上的my somewhat related question about elegant "ThenBy" sorting in JavaScript

答案 1 :(得分:1)

听起来他们正在以文本方式而不是数字方式进行排序。使用数字比较函数(请参阅参数示例here)。此外,要按两个字段排序,不要进行两次排序,请在同一个比较函数中进行两次比较。这应该让你排序(对不起):

function compareNumeric (a, b){return a-b}

self.linesSorted = ko.pureComputed(function () {
    return self.lines().sort(function (a, b) {
        return compareNumeric(a.lineType, b.lineType) ||  compareNumeric(a.lineGroupId, b.lineGroupId);
    })
});