angular-ui-grid

Angular UI-grid not sorting by date


I am using UI-grid, and I have a bunch of JS date objects like so:

"dob": new Date('1942-11-19')

I want to be able to filter the column by date when you click the "sort ascending/descending" buttons. As such, I have set the colDef up like so:

      {
        field: 'dob'
        , displayName: 'D.O.B.'
        , width: '130'
        , editableCellTemplate: '<div><form name="inputForm"><input type="INPUT_TYPE" ng-class="\'colt\' + col.uid" ui-grid-editor ng-model="MODEL_COL_FIELD" style="border-bottom-color: #74B3CE; border-bottom-width: 2px;"></form></div>'
        , headerCellClass: $scope.highlightFilteredHeader
        , cellTemplate: '<div class="ui-grid-cell-contents" >{{grid.getCellValue(row, col)| date:\'MM-dd-yyyy\'}}</div>'
        , cellFilter: 'date'
        , type: 'date'
      },

however, the column simply does not sort correctly. I even tried to set up a function to sort it from an external button like so:

      function mostRecent(){
        console.log('clicked mostRecent');
        $scope.gridApi.grid.sortColumn(
          $scope.gridApi.grid.getColumn('dob'), uiGridConstants.DESC
        );
        $scope.gridApi.grid.notifyDataChange(uiGridConstants.dataChange.ALL); //this line updates the rest of the columns accordingly
      };

But it also causes a mish-mush sort that is not correct. Does anyone know what the issue is? I thought it might have to do with my cellTemplate, but after removing the template, there wasn't a difference...


Solution

  • Yes you are right, ui-grid doesn't support sorting of Date type columns.

    However you can define a sortingAlgorithm in the columnDef.

    Here is how your column definition should look like:

    ...
    
    columnDefinition.sortingAlgorithm = function (firstDateString, secondDateString) {
      var dateFormat = 'YYYY-MM-DD';
      return function (firstDateString, secondDateString, dateFormat) {
        if (!firstDateString && !secondDateString) {
          return 0;
        }
    
        if (!firstDateString) {
          return 1;
        }
    
        if (!secondDateString) {
          return -1;
        }
    
        var firstDate = $window.moment(firstDateString, dateFormat);
        if (!firstDate.isValid()) {
          throw new Error('Invalid date: ', firstDateString);
        }
    
        var secondDate = $window.moment(secondDateString, dateFormat);
        if (!firstDate.isValid()) {
          throw new Error('Invalid date: ', secondDateString);
          }
    
        if (firstDate.isSame(secondDate)) {
          return 0;
        } else {
          return firstDate.isBefore(secondDate) ? -1 : 1;
        }
      };
    };
    
    ...
    

    Please note that in this example Moment.js is used. It is a very useful library so you might probably find also another place in your project where to use it.