dates not properly sorted in Angular.js

12,172

be aware that it will compare string. It won't compare Dates. You will have to deal with Dates object.

Here is a talk about this.

Here is the solution from vojtajina

Here is part of the solution:

Main.prototype = {

    sort: function(item) {
        if (this.predicate == 'date') {
            return new Date(item.date);
        }
        return item[this.predicate];
    },

    sortBy: function(field) {
        if (this.predicate != field) {
            this.predicate = field;
            this.reverse = false;
        } else {
            this.reverse = !this.reverse;
        }
    },

    reverse: false
};
Share:
12,172
Documental
Author by

Documental

Updated on June 15, 2022

Comments

  • Documental
    Documental almost 2 years

    I am relatively new to Angular.js and am having a problem with date sorting. I have looked around the web for similar issues, but haven't found any that are of quite the same flavor.

    The situation is as follows:

    I am getting a data set back from the database (that I would like to display in a column-header sortable table), in which each record contains a date formatted as a string:

    data = [
      {
        "name": "Test_1_Test",
        "creation_date": "8/2/2013 10:31:02 AM"
      },
      {
        "name": "Test_2_Test",
        "creation_date": "8/1/2013 9:12:32 AM"
      },
      {
        "name": "Test_3_Test",
        "creation_date": "9/13/2013 4:55:09 AM"
      }
    ]
    

    Additionally, I am getting back a set of column headers:

    headers = [
      {
        "column": "name",
        "label": "Doc Name"
      },
      {
        "column": "creation_date",
        "label": "Create Date",
        "displayFormat": {
          "dateType": "medium"
        }
      }
    ]
    

    Using an ng-repeat directive to create the column headers (no trouble there):

    <th ng-repeat="column in smartviewColumns">
      <a href="" ng-click="sortBy($index)">
        {{column.label}}
      </a>
    </th>
    

    where the sortBy function in the controller is as follows:

    $scope.sortBy = function(index){
      if ($scope.sortColumn && $scope.sortColumn === $scope.columns[index]) {
        $scope.reverse = !$scope.reverse;
      }
      $scope.sortColumn = $scope.columns[index];
    }
    

    Additionally, using nested ng-repeat directives to create the data rows (across each column) in the table:

    <tr ng-repeat="record in data | orderBy:sortColumn:reverse">
      <td ng-repeat="column in headers">
        <div ng-if="column.displayFormat && column.displayFormat.dateType">
          {{getDate(record[column]) | date:column.displayFormat.dateType}}
        </div>
        <div ng-if="!smartviewColumns[$index].displayFormat">
          {{record[smartviewColAttrs[$index]]}}
        </div>    
      </td>
    </tr>
    

    The issue is that the dates do not sort properly. When I reverse the order, the list flips but the mis-ordering persists. I have tried formatting the date string differently, as well as calling new Date(creation_date), both to no avail.

    Fiddle showing similar symptom

    Has anyone else experienced this issue? (Additionally, i should mention that i am using a paginator as a secondary filter on the data rows, but even when excluding it the behavior persists)

  • Documental
    Documental over 10 years
    Thanks for the feedback. This solution is limited to a hard coded key value of date. I need to apply this type of prototype for any data column whose header contains the key dateFormat, but the sort function only receives the item, which doesn't contain the header information. Can this type of prototyping be done within the angular module in such a way as to be aware of $scope, and thus the header information stored there? It seems that if so i could use that information to determine if the item needed to be a date or not.