jQuery UI Widgets Forums Grid Sorting Throws Errors + Sorting Alphanumerics

This topic contains 5 replies, has 2 voices, and was last updated by  Dimitar 9 years, 5 months ago.

Viewing 6 posts - 1 through 6 (of 6 total)
  • Author

  • jimiayler
    Participant

    Hello. We are using jQWidgets v3.7.1 and trying to sort columns in jqxGrid — we are including jqxGrid.sort.js. When I try to add parameters for “sortcolumn” or “sortdirection”, I get an error in the browser console, e.g.: “Uncaught Invalid property: sortcolumn” or “sortdirection”. Every other parameter does seem to work, including “sortable”.

    We also have a unique alphanumeric naming convention, “Foo-1,” “Foo-2” etc., that we’d like to sort by the last integer in the string, but because there are both alphabetic and numeric data in the name, 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 we would 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. We appreciate any help you might be able to provide us — thank you for your attention.


    Dimitar
    Participant

    Hello jimiayler,

    sortcolumn and sortdirection are properties of the grid source object, unlike sortable, which is a property of the main grid object. Here is how you can set them:

    var source = {
        datatype: "xml",
        datafields: [{
            name: 'ShippedDate',
            map: 'm\\:properties>d\\:ShippedDate',
            type: 'date'
        }, {
            name: 'Freight',
            map: 'm\\:properties>d\\:Freight',
            type: 'float'
        }, {
            name: 'ShipName',
            map: 'm\\:properties>d\\:ShipName',
            type: 'string'
        }, {
            name: 'ShipAddress',
            map: 'm\\:properties>d\\:ShipAddress',
            type: 'string'
        }, {
            name: 'ShipCity',
            map: 'm\\:properties>d\\:ShipCity',
            type: 'string'
        }, {
            name: 'ShipCountry',
            map: 'm\\:properties>d\\:ShipCountry',
            type: 'string'
        }],
        root: "entry",
        record: "content",
        id: {
            name: "OrderID",
            map: "m\\:properties>d\\:OrderID"
        },
        url: url,
        sortcolumn: 'ShipName',
        sortdirection: 'asc'
    };

    You can check the demo Custom Sorting where you can see a sample implementation of such a function. In your code, compare the values after “Foo-” only.

    Best Regards,
    Dimitar

    jQWidgets team
    http://www.jqwidgets.com/


    jimiayler
    Participant

    Great, thank you for the clarification, those do not throw errors now. However, I don’t see in your demo a clear example of comparing “the values after ‘Foo-‘ only” for our one sortable column. Would truly appreciate any guidance you might be able to provide here. Thanks again.


    Dimitar
    Participant

    Hi jimiayler,

    This is too specific a requirement and we cannot implement it for you, but here is what I meant by comparing the values after “Foo-” only:

    var compare = function(value1, value2) {
            value1 = value1.slice(4); // returns only the number after "Foo-"
            value2 = value2.slice(4); // returns only the number after "Foo-"
            ...

    Best Regards,
    Dimitar

    jQWidgets team
    http://www.jqwidgets.com/


    jimiayler
    Participant

    Unfortunately, that approach returns a sort that reads (assuming 11 results):

    Foo-2
    Foo-3
    Foo-4
    Foo-5
    Foo-1
    Foo-6
    Foo-7
    Foo-8
    Foo-9
    Foo-10
    Foo-11

    It is the same result whether one sorts ascending or descending. I confess I’m surprised no one has ever brought a similarly mixed alphanumeric sort case to your attention before, it seems as though it would be a pretty standard utilization. I’ll put in a request for future versions having this functionality. In the event I am getting the complete custom sorting scenario wrong, please see sample code below trying to get this going. Thank you once more for your attention and assistance.

    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 = value1.slice(5); // returns only the number after "Eval-"
            value2 = value2.slice(5); // returns only the number after "Eval-"
    
                try {
                        var tmpvalue1 = parseFloat(value1);
                        if (isNaN(tmpvalue1)) {
                            if (value1 < value2) { return -1; }
                            if (value1 > value2) { return 1; }
                    }
                    else {
                        var tmpvalue2 = parseFloat(value2);
                        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'
        };

    Dimitar
    Participant

    Hi jimiayler,

    An alphanumeric sort functionality may have been required by other users, too, but each time the actual scenario has been different – “Foo-2” in your case, “2-Foo” (for example) in someone else’s. That is why there is no definitive, built-in alphanumeric sorting.

    Here is a working modification of your code:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <link rel="stylesheet" href="../../jqwidgets/styles/jqx.base.css" type="text/css" />
        <script type="text/javascript" src="../../scripts/jquery-1.11.1.min.js"></script>
        <script type="text/javascript" src="../../jqwidgets/jqxcore.js"></script>
        <script type="text/javascript" src="../../jqwidgets/jqxdata.js"></script>
        <script type="text/javascript" src="../../jqwidgets/jqxbuttons.js"></script>
        <script type="text/javascript" src="../../jqwidgets/jqxscrollbar.js"></script>
        <script type="text/javascript" src="../../jqwidgets/jqxlistbox.js"></script>
        <script type="text/javascript" src="../../jqwidgets/jqxdropdownlist.js"></script>
        <script type="text/javascript" src="../../jqwidgets/jqxmenu.js"></script>
        <script type="text/javascript" src="../../jqwidgets/jqxgrid.js"></script>
        <script type="text/javascript" src="../../jqwidgets/jqxgrid.sort.js"></script>
        <script type="text/javascript" src="../../jqwidgets/jqxgrid.pager.js"></script>
        <script type="text/javascript" src="../../jqwidgets/jqxgrid.columnsresize.js"></script>
        <script type="text/javascript" src="../../jqwidgets/jqxgrid.selection.js"></script>
        <script type="text/javascript" src="../../scripts/demos.js"></script>
        <script type="text/javascript" src="generatedata.js"></script>
        <script type="text/javascript">
            $(document).ready(function () {
                // prepare the data
                var data = [{ firstname: 'Foo-1' }, { firstname: 'Foo-2' }, { firstname: 'Foo-11' }, { firstname: 'Foo-10'}];
    
                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 < data.length; i++) {
                            sortdata.push(data[i]);
                        }
                    }
                    else sortdata = data;
    
                    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 = value1.firstname.slice(4); // returns only the number after "Foo-"
                    value2 = value2.firstname.slice(4); // returns only the number after "Foo-"
    
                    try {
                        var tmpvalue1 = parseFloat(value1);
                        if (isNaN(tmpvalue1)) {
                            if (value1 < value2) { return -1; }
                            if (value1 > value2) { return 1; }
                        }
                        else {
                            var tmpvalue2 = parseFloat(value2);
                            if (tmpvalue1 < tmpvalue2) { return -1; }
                            if (tmpvalue1 > tmpvalue2) { return 1; }
                        }
                    }
                    catch (error) {
                        var er = error;
                    }
    
                    return 0;
    
                };
    
                var source =
                {
                    localdata: data,
                    sort: customsortfunc,
                    datafields:
                    [
                        { name: 'firstname', type: 'string' }
                    ],
                    datatype: "array"
                };
                var dataAdapter = new $.jqx.dataAdapter(source);
    
                $("#evaluations-grid").jqxGrid(
                {
                    width: 200,
                    source: dataAdapter,
                    sortable: true,
                    autoheight: true,
                    ready: function () {
                        $("#evaluations-grid").jqxGrid('sortby', 'firstname', 'asc');
                    },
                    columns: [
                      { text: 'First Name', datafield: 'firstname', width: 200 }
                    ]
                });
            });
        </script>
    </head>
    <body class='default'>
        <div id="evaluations-grid">
        </div>
    </body>
    </html>

    Best Regards,
    Dimitar

    jQWidgets team
    http://www.jqwidgets.com/

Viewing 6 posts - 1 through 6 (of 6 total)

You must be logged in to reply to this topic.