同时排序和订阅Knockout可观察数组

时间:2019-06-06 17:01:33

标签: sorting knockout.js subscribe

我正在尝试排序和订阅可观察的数组。我不能让两个人同时工作。我认为它必须做数组的类型。我有两个名为“ AttendanceArray”的数组,其中一个已被注释掉。活动数组允许单击一个复选框,该复选框使用subscription方法跟踪记录。使用此数组,列链接不起作用。如果您反转注释哪个数组,则排序将起作用。我正在尝试使两个功能同时工作。

AttendanceArray: ko.observableArray([
    new rosterItem(101, "J", "Smith", "RN Staff Nurse", false),
    new rosterItem(102, "T", "Davis", "LPN Staff Nurse", true),
    new rosterItem(103, "M", "Glass", "Resident Assistance", false),
    new rosterItem(104, "D", "Black", "Practioner", true)
    ]),

/*
    AttendanceArray: ko.observableArray([
    {ID: 101, FirstName: "J", LastName: "Smith", Title: "RN Staff Nurse", Present: false},
    {ID: 102, FirstName: "T", LastName: "Davis", Title: "LPN Staff Nurse", Present: true},
    {ID: 103, FirstName: "M", LastName: "Glass", Title: "Resident Assistance", Present: false},
    {ID: 104, FirstName: "D", LastName: "Black", Title: "Practioner", Present: true}
    ]),
    */

https://jsfiddle.net/jjfrick/0ykasv4b/63/

1 个答案:

答案 0 :(得分:3)

使用rosterItem实例的实现中的排序在可观察对象和不可观察对象的比较中存在一些问题。

在下面的(可运行)示例中,主要更改包括

  • 将视图模型FirstNameLastNameTitle更改为不可观察对象。
  • 使用括号在Present上进行比较,因为它是可观察的

    if (a.Present() === b.Present())
    

var rosterItem = function (id, firstName, lastName, title, present) {
    
    this.ID = ko.observable(id);
    this.FirstName = firstName;
    this.LastName = lastName;
    this.Title = title;
    this.Present = ko.observable(present);
    this.PresentOriginal = ko.utils.unwrapObservable(this.Present);

    // Subscribe when checked changes and push or remove items
    this.Present.subscribe(function () {
        if (this.Present() != this.PresentOriginal) {
            viewModel.changedAttendance.push(this);
        }
        else {
            viewModel.changedAttendance.remove(this);
        }
    }.bind(this));
};

var viewModel = {

    AttendanceArray: ko.observableArray([
        new rosterItem(101, "J", "Smith", "RN Staff Nurse", false),
        new rosterItem(102, "T", "Davis", "LPN Staff Nurse", true),
        new rosterItem(103, "M", "Glass", "Resident Assistance", false),
        new rosterItem(104, "D", "Black", "Practioner", true)
        ]),


    changedAttendance: ko.observableArray([]),
    selectedSortBy: ko.observable("Present"),
}
viewModel.setSortOrder = function (item) {
    switch (item) {
        case 'FirstName':
            this.selectedSortBy('FirstName');         
            break;
        case 'LastName':
            this.selectedSortBy('LastName');
            break;
        case 'Title':
            this.selectedSortBy('Title');
            break;
        case 'Present':
            this.selectedSortBy('Present');
            break;
    }
}.bind(viewModel);

viewModel.sortByTitle = function (a, b) {  // sort by ListOrder column
    if (a.Title === b.Title) {
        return 0;
    } else {
        return (a.Title < b.Title) ? -1 : 1;
    }
}.bind(viewModel);

viewModel.sortByPresent = function (a, b) {  // sort by ListOrder column
            
    if (a.Present() === b.Present()) {
        return 0;
    }
    else {
        return (a.Present() > b.Present()) ? -1 : 1;
    }
}.bind(viewModel);

viewModel.sortByFirstName = function (a, b) {  // sort by ListOrder column

    if (a.FirstName === b.FirstName) {
        return 0;
    }
    else {
        return (a.FirstName < b.FirstName) ? -1 : 1;
    }
}.bind(viewModel);

viewModel.sortByLastName = function (a, b) {  // sort by ListOrder column
    
    if (a.LastName === b.LastName) {
        return 0;
    }
    else {
        return (a.LastName < b.LastName) ? -1 : 1;
    }
}.bind(viewModel);

ko.applyBindings(viewModel);
#list_wrapper {
    width: 500px;
}

ul.multiple_columns li {
    text-align: left;
    float: left;
    list-style: none;
    height: 30px;
    width: 100px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>

        <div class="tableView">
            <div id="list_wrapper">
                <ul class="multiple_columns">
                    <li><a href="#" data-bind="click: function () { $root.setSortOrder('FirstName') }">FirstName</a></li>
                    <li><a href="#" data-bind="click: function () { $root.setSortOrder('LastName') }">LastName</a></li>
                    <li><a href="#" data-bind="click: function () { $root.setSortOrder('Title') }">Title</a></li>
                    <li><a href="#" data-bind="click: function () { $root.setSortOrder('Present') }">Present</a></li>
                </ul>
            </div>
 

            <!-- ko if: $root.selectedSortBy() === 'FirstName' -->
                <div data-bind="template: { name: 'AttendanceList', foreach: $root.AttendanceArray().sort($root.sortByFirstName) }"></div>
            <!-- /ko -->
            <!-- ko if: $root.selectedSortBy() === 'LastName' -->
                <div data-bind="template: { name: 'AttendanceList', foreach: $root.AttendanceArray().sort($root.sortByLastName) }"></div>
            <!-- /ko -->
            <!-- ko if: $root.selectedSortBy() === 'Title' -->
                <div data-bind="template: { name: 'AttendanceList', foreach: $root.AttendanceArray().sort($root.sortByTitle) }"></div>
            <!-- /ko -->
            <!-- ko if: $root.selectedSortBy() === 'Present' -->
                <div data-bind="template: { name: 'AttendanceList', foreach: $root.AttendanceArray().sort($root.sortByPresent) }"></div>
            <!-- /ko -->
        </div>
    </div>
    <div id="changedList">
        Changed List to Send to server: ( Count: <span data-bind="text: changedAttendance().length"></span> )
        <ul data-bind=" template : { name : 'changedAttendanceTemplate', foreach: changedAttendance }"></ul>
    </div>
 </script>

<script id="AttendanceList" type="text/html">
    <div id="list_wrapper">
        <ul class="multiple_columns">
            <li data-bind="text: FirstName"></li>
            <li data-bind="text: LastName"></li>
            <li data-bind="text: Title"></li>
            <li><input type="checkbox" data-bind="checked: Present" /></li>
        </ul>
    </div>

</script>
<script id="changedAttendanceTemplate" type="text/html">
    <li>
        <span data-bind="text: ID"/>
    </li>
</script>
<pre data-bind="text: ko.toJSON($data, null, 2)"></pre>