0

So i am trying to sort multiple columns at the same time. Ex. if i am sorting a table in ascending order to see if my accounts are activated or not. then at the same time i want the list to be automatically sorted in ascending order by there last name. Here is the code:

   <table class="table table-hover admin-table">
    <thead>
        <tr>
            <th data-bind="click: function () { setSort('FirstName'); }, css: { 'active-sort': $root.sortColumn() == 'FirstName', 'asc': $root.sortColumn() == 'FirstName' && $root.sortDirection() == 'ASC', 'desc': $root.sortColumn() == 'FirstName' && $root.sortDirection() == 'DESC' }">First Name<i></i></th>
            <th data-bind="click: function () { setSort('LastName'); }, css: { 'active-sort': $root.sortColumn() == 'LastName', 'asc': $root.sortColumn() == 'LastName' && $root.sortDirection() == 'ASC', 'desc': $root.sortColumn() == 'LastName' && $root.sortDirection() == 'DESC' }">Last Name<i></i></th>
            <th data-bind="click: function () { setSort('Email'); }, css: { 'active-sort': $root.sortColumn() == 'Email', 'asc': $root.sortColumn() == 'Email' && $root.sortDirection() == 'ASC', 'desc': $root.sortColumn() == 'Email' && $root.sortDirection() == 'DESC' }">Email<i></i></th>
            <th data-bind="click: function () { setSort('IsActivated', 'LastName'); }, css: { 'active-sort': $root.sortColumn() == 'IsActivated', 'asc': $root.sortColumn() == 'IsActivated' && $root.sortDirection() == 'ASC', 'desc': $root.sortColumn() == 'IsActivated' && $root.sortDirection() == 'DESC' }">Is Activated<i></i></th>
            <th data-bind="click: function () { setSort('IsAdministrator'); }, css: { 'active-sort': $root.sortColumn() == 'IsAdministrator', 'asc': $root.sortColumn() == 'IsAdministrator' && $root.sortDirection() == 'ASC', 'desc': $root.sortColumn() == 'IsAdministrator' && $root.sortDirection() == 'DESC' }">Is Administrator<i></i></th>
            <th></th>
        </tr>
    </thead>
    <tbody data-bind="foreach: accounts">
        <tr>
            <td data-bind="text: FirstName"></td>
            <td data-bind="text: LastName"></td>
            <td data-bind="text: Email"></td>
            <td data-bind="text: IsActivated() ? 'Yes' : 'No'"></td>
            <td data-bind="text: IsAdministrator() == 'true' ? 'Yes' : 'No'"></td>
            <td>
                <button class="btn-std" data-bind="click: $root.showUpdateModal">Update</button> 
                <div class="clearfix"></div>
                <button class="btn-std" data-bind="click: $root.resendVerificationEmail, visible: !IsActivated()">Resend Verification Email</button>
            </td>
        </tr>
    </tbody>
</table>

Java Script:

        self.renderUsers = function (pageIndex, pageSize) {
        var filteredUsers;

        if (self.sortColumn() == "IsActivated") {
            if (self.sortDirection() == "ASC") {
                filteredUsers = Enumerable.from(allAccounts).orderBy("$." + self.sortColumn() + "()").skip((pageIndex - 1) * pageSize).take(pageSize).toArray();
            } else {
                filteredUsers = Enumerable.from(allAccounts).orderByDescending("$." + self.sortColumn() + "()").skip((pageIndex - 1) * pageSize).take(pageSize).toArray();

            }
        }
        else {
            if (self.sortDirection() == "ASC") {
                filteredUsers = Enumerable.from(allAccounts).orderBy("$." + self.sortColumn() + "().toUpperCase()").skip((pageIndex - 1) * pageSize).take(pageSize).toArray();
            } else {
                filteredUsers = Enumerable.from(allAccounts).orderByDescending("$." + self.sortColumn() + "().toUpperCase()").skip((pageIndex - 1) * pageSize).take(pageSize).toArray();
            }
        }

        self.accounts(filteredUsers);
    };
  • possible duplicate of [Javascript, how do you sort an array on multiple columns?](http://stackoverflow.com/questions/2784230/javascript-how-do-you-sort-an-array-on-multiple-columns) – PW Kad Jul 04 '14 at 00:50

2 Answers2

1

To sort you should be using the sort function on the observable array.

To sort on both IsActivated and LastName you would do this:

self.accounts.sort(function (l, r) { return l.IsActivated === r.IsActivated 
    ? l.LastName > r.LastName ? 1 : -1
    : l.IsActivated > r.IsActivated ? 1 : -1 });

http://jsfiddle.net/Wk7dr/4/

Wayne Ellery
  • 7,888
  • 1
  • 28
  • 45
  • Well the main reason i want something similar than mine is due to the fact that, i dont need a button. I should be able to click on isActivated and both lastname and isactivate sort should be activated. – Nitin Jaitely Jul 04 '14 at 16:01
  • and moreover, i am just trying to add the functionality (as minimal changes as possible) to an existing software, instead of changing a lot of modules. – Nitin Jaitely Jul 04 '14 at 16:25
0

I posted a proof of concept here:

http://jsfiddle.net/ERN4w/

The fiddle is a very simple example, but the functional part can be condensed to the following:

// Assuming criteria is an array of sort criteria, something like:
//
// criteria = [{
//     order: true, // ascending, false for descending
//     property: 'lastName'
// }, {
//     order: true, // ascending, false for descending
//     property: 'firstName'
// }];
//
observableItems.sort(function (item1, item2) {
    var comparison = 0,
        i = 0;

    while (comparison === 0 && i < criteria.length) {
        comparison = compareValues(criteria[i].order,
            item1[criteria[i].property],
            item2[criteria[i].property]);

        i += 1;
    }

    return comparison;
});

'compareValues' is a function with the following signature:

function compareValues(ascending, value1, value2) {
    // Compare value1 to value2 and return 1, -1, or 0.
}

The jsFiddle uses a ko.computed and an observableArray of sorting criteria to sort the items. Items sort dynamically depending on changes to the sorting criteria.

Hope this is of some use to you.

Paul
  • 1,502
  • 11
  • 19