2

I'm trying to sort a list of physicians on a page by name. There is a dropdown and the user can select ascending or descending. Neither one is working. The UI is not updating at all.

EDIT: I've changed the sort code to follow the example on the KO website. When i step into the code i get an error when I hover over left and it says "'left' is not defined"

function SortDownloadPhysicians(){
    var sortDirection = getSortDirection()
    var sortByParam = getSortByParam()

    if(sortByParam === "name"){
        if(sortDirection === "ascending"){
            self.physicians().sort(function (left, right) { return left.name == right.name ? 0 : (left.name < right.name ? -1 : 1) });
        }else{
            self.physicians().sort(function (left, right) { return left.name == right.name ? 0 : (left.name > right.name ? -1 : 1) });
        }
    }
    else{  //date of birth
        if(sortDirection === "ascending"){
            self.physicians().sort(function (left, right) { return left.dateOfBirth == right.dateOfBirth ? 0 : (left.dateOfBirth < right.dateOfBirth ? -1 : 1) });
        }else{
            self.physicians().sort(function (left, right) { return left.dateOfBirth == right.dateOfBirth ? 0 : (left.dateOfBirth > right.dateOfBirth ? -1 : 1) });
        }
    }

Here's my sort function

function sortDownloadPage() {

    var sortDirection = getSortDirection();
    var sortBy = getSortBy();


    // sort by name
    if (sortDirection === "ascending") {

        self.physicians().sort(function (a, b) {

             if (a.name().toLowerCase() > b.name().toLowerCase()) {
                return 1;
            }
             if (a.name().toLowerCase() < b.name().toLowerCase()) {
                return -1;
            }
            // a must be equal to b
            return 0;
        });


    } else {

         self.physicians().sort(function (a, b) {

             if (a.name().toLowerCase() < b.name().toLowerCase()) {
                return 1;
            }
             if (a.name().toLowerCase() > b.name().toLowerCase()) {
                return -1;
            }
            // a must be equal to b
            return 0;
        });
    }
};

and here's part of the view model

 var ViewModels = ViewModels || {};
    (function (ViewModels) {
        var DownloadVM = function (options) {
            options = $.extend({
                physicians: ko.utils.unwrapObservable(options.physicians || [])
            }, options);


            //********************************************************************************
            // Private properties

            var self = this,
                _physicians = ko.observableArray([]),
                _page = 1,
                _pageSize = 2;


            //********************************************************************************
            // Public properties



            self.physicians = ko.computed(function () {
                return ko.utils.unwrapObservable(_physicians);
            });

UI code

<div class="grid-list-group" data-bind="template: { name: 'physicianDownloadTemplate', foreach: physicians }">



    <script type="text/html" id="physicianDownloadTemplate">
        <div class="group-item clearfix" data-bind="fxVisibility: visible">
            <div class="item-col selector">
                <input type="checkbox" data-bind="checked: checked">
            </div>
            <div class="item-col photo hidden-sm hidden-xs" data-bind="click: $root.toggleOpenState">
                <img class="rounded" title="Profile Picture" src="@Url.Content("~/Content/Images/profile-default.png")">
            </div>
            <div class="item-col field name" onclick="$(this).parent().children('.group-item-drawer').slideToggle();">
                <div class="caption">Physician Name</div>
                <div class="value" data-bind="text: name">{NAME}</div>
            </div>
            <div style="float: right;">
                <div class="item-col field date-of-birth">
                    <div class="caption">Date of Birth</div>
                    <div class="value" data-bind="text: dateOfBirth">{DATE OF BIRTH}</div>
                </div>

            </div>
            <div class="group-item-drawer clearfix" style="display: none; clear: both;" data-bind="template: { name: 'downloadItemTemplate', foreach: files }"></div>

        </div>
    </script>
3
  • This functionality is built right into Knockout. See: knockoutjs.com/documentation/… Commented Nov 17, 2014 at 21:31
  • A big problem with the code, as written above is that: self.physicians().sort() returns a sorted array; it doesn't modify the original array; so that line is doing nothing. Commented Nov 18, 2014 at 0:35
  • Retsam, how do I make it modifiy the original array so that the UI updates? Commented Nov 18, 2014 at 21:48

1 Answer 1

2

I typically solve this problem using a computed function. The computed can subscribe to the "sorting" variable, so when it changes, it will recompute based on the new variable. From there, it is simply a matter of returning the appropriate sorting.

function vm() {
    var physicians = [
        'smith',
        'grant',
        'foreman'
    ];

    this.sorting = ko.observable();
    this.sortingOptions = ['A-Z', 'Z-A'];
    this.physicians =  ko.computed(function() {
        var sorting = this.sorting(),
            sorted = physicians.slice().sort();
        if (sorting == 'Z-A')
            sorted.reverse();
        return sorted;
    });
}
ko.applyBindings(new vm());

and in the view

<select data-bind="options: sortingOptions, value: sorting"></select>
<select data-bind="options: physicians"></select>
Sign up to request clarification or add additional context in comments.

1 Comment

I didn't go into your sorting logic, which is much better than mine, because the question was less about how to sort and more about how to sort using knockout. So don't steal my crappy sorting function, it will ruin your beautiful app.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.