Search code examples
sortingjqxgridjqwidget

Alphanumeric Sort in jqxGrid


I am using jQWidgets v3.7.1 and trying to sort columns in jqxGrid with a unique alphanumeric naming convention, “Foo-1,” “Foo-2″ etc., that I'm trying to sort by the last integer in the string, but because there are both alphabetic and numeric data in the string, the closest we can get is a sort that goes something like:

Foo-1

Foo-10

Foo-11

Foo-2

Foo-3 etc.

I know there are custom sorting abilities for the grid, but it’s not clear to me how to accomplish this sorting challenge that way. We really do not want to change our data structure to something like “Foo-01″, “Foo-02″ if at all possible. Thanks for any help you might be able to provide.

UPDATE: FYI, I have tried a variation of the custom sorting example provided by jqWidgets:

// prepare the data
var dataFields = 
[
    { name: 'session_name', type: 'string' },
    { name: 'current_phase', type: 'string' },
    { name: 'current_stage', type: 'string' },
    { name: 'contractor_last_name', type: 'string' },
    { name: 'contractor_first_name', type: 'string' },
    { name: 'contractor_email', type: 'string' },
    { name: 'contractor_company_name', type: 'string' },
    { name: 'engagement_manager_last_name', type: 'string' },
    { name: 'engagement_manager_first_name', type: 'string' },
    { name: 'engagement_manager_email', type: 'string' },
    { name: 'department', type: 'string' },
    { name: 'start_time', type: 'date'  },
    { name: 'outcome', type: 'string' },
    { name: 'outcome_report_file_name', type: 'string' },
    { name: 'end_time', type: 'date'  },
    { name: 'jurisdictions', type: 'string' },
    { name: 'nls_session_id', type: 'string' },
    { name: 'next_steps_url', type: 'string' },
    { name: 'action_taken', type: 'string' },
];

 var customsortfunc = function (column, direction) {
            var sortdata = new Array();

            if (direction == 'ascending') direction = true;
            if (direction == 'descending') direction = false;

            if (direction != null) {
                for (i = 0; i < dataFields.length; i++) {
                    sortdata.push(dataFields[i]);
                }
            }
            else sortdata = dataFields;

            var tmpToString = Object.prototype.toString;
            Object.prototype.toString = (typeof column == "function") ? column : function () { return this[column] };
            if (direction != null) {
                sortdata.sort(compare);
                if (!direction) {
                    sortdata.reverse();
                }
            }
            source.localdata = sortdata;
            $("#evaluations-grid").jqxGrid('updatebounddata', 'sort');
            Object.prototype.toString = tmpToString;
        }


var compare = function (value1, value2) {
    value1 = String(value1).toLowerCase();
    value2 = String(value2).toLowerCase();

    try {
        var tmpvalue1 = parseFloat(value1.replace(/Foo\-/, ''));
        if (isNaN(tmpvalue1)) {
            if (value1 < value2) { return -1; }
            if (value1 > value2) { return 1; }
        }
        else {
            var tmpvalue2 = parseFloat(value2.replace(/Foo\-/, ''));
            if (tmpvalue1 < tmpvalue2) { return -1; }
            if (tmpvalue1 > tmpvalue2) { return 1; }
        }
    }
    catch (error) {
        var er = error;
    }

    return 0;
};

var source =
{
    datatype: "json",
    datafields: dataFields,
    id: 'session_name',
    url: url,
    sort: customsortfunc,
    sortcolumn: 'session_name',
    sortdirection: 'asc'
};

but this not only gives me an even more incorrect series of results, viz.:

Foo-2

Foo-3

Foo-4

Foo-5

Foo-1

Foo-6

Foo-7 etc.

but if I try to change the sorting direction, I go from 11 results to 19, except the data is completely gone.


Solution

  • You can use custom compare function by replacing Foo- part (or all non digit characters), something like (taken from jqxgrid customsort example):

    var compare = function (value1, value2) {
        value1 = String(value1).toLowerCase();
        value2 = String(value2).toLowerCase();
    
        try {
            var tmpvalue1 = parseFloat(value1.replace(/Foo\-/, ''));
            if (isNaN(tmpvalue1)) {
                if (value1 < value2) { return -1; }
                if (value1 > value2) { return 1; }
            }
            else {
                var tmpvalue2 = parseFloat(value2.replace(/Foo\-/, ''));
                if (tmpvalue1 < tmpvalue2) { return -1; }
                if (tmpvalue1 > tmpvalue2) { return 1; }
            }
        }
        catch (error) {
            var er = error;
        }
    
        return 0;
    };