How to sort time column in jsgrid?

528 views Asked by At

We are binding a table using jqgrid. We have the first column start as a time column with a 12-hour format. We are facing an issue with sorting this data. The data is sorted correctly but it is not taking am/pm into consideration. Below is our code for binding the jqgrid:

var newFieldsArray =
        [
            { name: "ID", title: "ID", type: "number", width: "50px", visible: false },
            {
                name: "TimeStart", title: "Start", type: "customTime", width: "100px", validate: "required",
                sorttype: "date",
                formatter : {     
                    date : {       
                    AmPm : ["am","pm","AM","PM"],       
                    }     
                },
                // datefmt: "m/d/Y h:i A",
                //sorttype: 'datetime', formatter: 'date', formatoptions: {newformat: 'd/m/y', srcformat: 'Y-m-d H:i:s'},
                insertTemplate: function () {
                    var $result = jsGrid.fields.customTime.prototype.insertTemplate.call(this); // original input

                    $result.val(varendTime);

                    return $result;
                },
                itemTemplate: function (value, item) {
                    return "<b style='display:none'>" + Date.parse(item.StartDate) + "</b><span>" + (item.TimeStart) + "</span>";
                }
            },
            {
                name: "TimeEnd", title: "End", type: "customTime", width: "100px", validate: "required",sorttype: "date", datefmt: "h:i"
            },
            { name: "TimeTotal", title: "Time", type: "text", width: "50px", readOnly: true },
            {
                name: "CoilPO", title: "Coil PO", type: "text", width: "50px", validate: "required",
                insertTemplate: function () {
                    var $result = jsGrid.fields.text.prototype.insertTemplate.call(this); // original input

                    $result.val(varlot);

                    return $result;
                }
            },
            { name: "Joints", title: "Joints", type: "integer", width: "60px" },
            { name: "CommercialGrade", title: "Commercial Grade", type: "integer", width: "80px" },
            { name: "QAHold", title: "QA Hold", type: "integer", width: "60px" },
            { name: "Rejected", title: "Reject", type: "integer", width: "60px" },
            { name: "ActionTaken", title: "Reason of Delay / Action Taken", type: "text", width: "120px" },
            {
                name: "ClassId", title: "Class",
                type: "select", items: classDataArr,//classData.filter(function(n){return classdt.indexOf(n.Id) != -1 }),//classData,
                valueField: "Id", textField: "Title",
                insertTemplate: function () {
                    debugger;
                    var taxCategoryField = this._grid.fields[12];
                    var $insertControl = jsGrid.fields.select.prototype.insertTemplate.call(this);

                    var classId = 0;
                    var taxCategory = $.grep(voiceData, function (team) {
                        return (team.ClassId) === classId && (team.StationId) == parseInt($('#ddlEquipmentName').val());
                    });
                    taxCategoryField.items = taxCategory;
                    $(".tax-insert").empty().append(taxCategoryField.insertTemplate());

                    $insertControl.on("change", function () {
                        debugger;
                        var classId = parseInt($(this).val());
                        var taxCategory = $.grep(voiceData, function (team) {
                            return (team.ClassId) === classId && (team.StationId) == parseInt($('#ddlEquipmentName').val());
                        });
                        taxCategoryField.items = taxCategory;
                        $(".tax-insert").empty().append(taxCategoryField.insertTemplate());
                    });

                    return $insertControl;
                },
                editTemplate: function (value) {
                    var taxCategoryField = this._grid.fields[12];
                    var $editControl = jsGrid.fields.select.prototype.editTemplate.call(this, value);

                    var changeCountry = function () {
                        var classId = parseInt($editControl.val());
                        var taxCategory = $.grep(voiceData, function (team) {
                            return (team.ClassId) === classId && (team.StationId) == parseInt($('#ddlEquipmentName').val());
                        });
                        taxCategoryField.items = taxCategory;
                        $(".tax-edit").empty().append(taxCategoryField.editTemplate());
                    };
                    debugger;
                    $editControl.on("change", changeCountry);
                    changeCountry();
                    return $editControl;
                }
            },
            {
                name: "VoiceId", title: "Voice", type: "select", items: voiceData,
                valueField: "Id", textField: "Title", width: "120px", validate: "required",
                insertcss: "tax-insert",
                editcss: "tax-edit",
                itemTemplate: function (teamId) {
                    var t = $.grep(voiceData, function (team) { return team.Id === teamId; })[0].Title;
                    return t;
                },
            },
            { name: "Remarks", title: "Remarks", type: "text", width: "110px" },
            { name: "control", type: "control" }
        ];

    hoursGrid.jsGrid("option", "fields", newFieldsArray);

Below is two screenshots of data that appear when we sort: Ascending

Descending

Can someone tell me what we are doing wrong?

2

There are 2 answers

3
OfirD On

You're mixing up jsGrid and jqGrid. The way to achieve it in jsGrid is using the built-in sorter jsGrid.sortStrategies.date, I added an example below.

As commented by @Tomy Tomov (the creator of jqGrid), you're using jsGrid, not jqGrid. This is evident both by your code and by the UI in the screenshot.

Specifically, you took the date sorter of jqGrid and used it in your jsGrid code, but (of course) it's not supported there. You can go ahead and look in jsGrid source for AmPm which you used - and see it's not there.

So how to do it in jsGrid?

Just pass the built-in sorter jsGrid.sortStrategies.date to the sorter property. However, it does require Date objects, so if you only got time strings, you'll have to convert those to dates.

Below is a quick demo (jsfiddle), click the date column title to sort:

  • Note that getData gets a function parameter that is responsible to get all data as Date objects, and that the value of isUTC depends on whether you actually use it
    $(document).ready(function () {
        const dataFunc = getDataTimes;
        $("#jsGrid").jsGrid({
            width: "100%",
            data: getData(dataFunc),
            sorting: true,
            fields: [{ 
              name: "name",
              type: "text", 
              width: 50 
            }, { 
              name: "date", 
              type: "date", 
              width: 50, 
              sorter: jsGrid.sortStrategies.date, 
              cellRenderer: (value, item) => {
                const withYear = false;
                const isUTC = dataFunc == getDataTimes;
                return renderDateTime(value, item, withYear, isUTC);
              }
            }
          ]
        });
    });
    
    function getData(getDates) {
      const data = [
        {name: "a"}, {name: "b"}, {name: "c"},
        {name: "d"}, {name: "e"}, {name: "f"},
      ];
      const dates = getDates();
      for (let i = 0; i < dates.length; i++) {
        data[i].date = dates[i];
      }
      return data;
    }
    
    function getDataDates() {
      const date1 = new Date(2022, 10, 1, 4, 50);
      const date2 = new Date(2022, 10, 1, 8, 50);   
      const date3 = new Date(2022, 10, 1, 15, 50);  
      const date4 = new Date(2021, 10, 1, 4, 50);
      const date5 = new Date(2021, 10, 1, 8, 50);
      const date6 = new Date(2021, 10, 1, 15, 50);
      return [date1, date2, date3, date4, date5, date6];
    }
    
    function getDataTimes() {
      const time1 = "3:50 AM";
      const time2 = "8:50 AM";
      const time3 = "4:50 AM";
      const time4 = "3:50 PM";
      const time5 = "8:50 PM";
      const time6 = "4:50 PM";
      const times = [time1, time2, time3, time4, time5, time6];
      return times.map(t => convertTime12to24(t));
    }
    
    function convertTime12to24(time12h) {
      const [time, modifier] = time12h.split(' ');
      let [hours, minutes] = time.split(':');
      if (modifier === 'PM') {
        hours = parseInt(hours, 10) + 12;
      }
      return new Date(Date.UTC(2022,0,1,hours, minutes));
    }
    
    function renderDateTime(value, row, withYear, isUTC) {
      return `<td>${getDateTimeAsString(value, withYear, isUTC)}</td>`;
    }
    
    function getDateTimeAsString(date, withYear, isUTC) {
      var options = {
        hour: 'numeric', 
        minute: 'numeric', 
        hour12: true
      };
      if (withYear) {
        options.withYear = 'numeric';
      }
      if (isUTC) {
        options.timeZone = 'UTC';
      }
      return date.toLocaleString('en-US', options);
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jsgrid/1.5.3/jsgrid.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.13.2/jquery-ui.min.js"></script>
    <link href="https://cdnjs.cloudflare.com/ajax/libs/jsgrid/1.5.3/jsgrid-theme.min.css" rel="stylesheet">
    <link href="https://cdnjs.cloudflare.com/ajax/libs/jsgrid/1.5.3/jsgrid.min.css" rel="stylesheet">
    
    <div id="jsGrid" class="jsgrid"></div>
0
Ask Athar On

Let me give it a try, we have 2 options to perform Sorting operation in JsGrid: 1.Custom Field (Topic Name you can refer below link) Reference Link :http://js-grid.com/docs/#grid-fields

In this, you can define custom property in your config and extend it. You can use sorter property and call your user defined function werein you can logic to sort date with time stamps directly.

2.Sorting Strategies (Topic Name you can refer below link) Reference Link :http://js-grid.com/docs/#grid-fields

In this, you can create your custom objects and then apply sorting strategies of date directly on to the object to perform sorting operation as per your logic.