Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AngularJS ngTable filtering by Date

I'm trying to set up ngTable in my application, but it doesn't support filtering by Date, and I can't figure out how to implement it. I initially had the date in my data as a timestamp, which allowed me to sort the column properly due to the incremental nature of a timestamp, but obviously I can't type September and filter the data.

// Example row data from data array
{
  "index": 0,
  "id": "54587313ac91d561b246bf90",
  "user": "user3",
  "date": 1390054873445,
  "status": "in-progress"
}

I tried setting it to a string, but when you filter or sort it doesn't produce a asc/desc order instead it comes in order it is organized in the data.

// Date output not in asc/desc if use date string
September 8, 2014
September 27, 2014
September 23, 2014
September 26, 2014

I've been looking through ngTable and found I could alter the header of the table, so I grabbed a copy to edit and add some sort of custom filter or directive? Maybe I should be using a different date string? I created a Plunker of the app using the timestamp data, which is filtered for display to the user and sortable, but I'd like to be able to filter by typing the month, day, and/or year, ie. 2014, September, etc.

// Example date column setup
<td data-title="'Date'" 
    sortable="'date'" 
    filter="{ 'date': 'text' }"
    ng-bind="(doc.date | date:mediumDate)"></td>

UPDATE I just noticed at the bottom of ngTable.js that you can drop in your own filters. I eventually figured out how to load an external file to a custom filter instead of inlining ngTemplates:

<td data-title="'Date'" 
    sortable="'date'" 
    filter="{ 'date': 'date' }" // add name of filter (date), to the value of assoc array
    ng-bind="(loan.date | date:mediumDate)"></td>

or to place the file in a more useful place in your application:

<td data-title="'Date'" 
    sortable="'date'" 
    filter="{ 'date': 'date', templateURL: '/www/app/ng-table/filters/date.html' }"
    ng-bind="(loan.date | date:mediumDate)"></td>

Still not sure what to do, but will keep trying to get this working, I made a Plunker of what I have so far if that helps. Should this be a directive in date.html?

like image 364
mtpultz Avatar asked Nov 04 '14 07:11

mtpultz


1 Answers

You could do this by defining a custom filter like this:

angular.module("tableApp", ['ngTable'])

.filter('customUserDateFilter', function($filter) {
    return function(values, dateString) {
     var filtered = [];
  
      if(typeof values != 'undefined' && typeof dateString != 'undefined') {
        angular.forEach(values, function(value) {
            if($filter('date')(value.Date).indexOf(dateString) >= 0) {
              filtered.push(value);
            }
          });
      }
      
      return filtered;
    }
})

.controller("MyCtrl", function($scope, $filter, ngTableParams) {
  var data = [
    { Name: 'John', Date: new Date('1/1/2014') },
    { Name: 'Doe', Date: new Date('1/2/2014') },
    { Name: 'Jane', Date: new Date('2/1/2014') }
  ];
  
    $scope.tableParams = new ngTableParams({
        page: 1,            // show first page
        count: 10,          // count per page
    }, {
        total: data.length, // length of data
        getData: function($defer, params) {
            // use build-in angular filter
            var filters = params.filter();
            var tempDateFilter;
            
            var orderedData = params.sorting() ?
                            $filter('orderBy')(data, params.orderBy()) :
                            data;

            if(filters) {
              if(filters.Date) {
                orderedData = $filter('customUserDateFilter')(orderedData, filters.Date);
                tempDateFilter = filters.Date;
                delete filters.Date;
              }
              orderedData = $filter('filter')(orderedData, filters); 
              filters.Date = tempDateFilter;
            }

            $scope.users = orderedData.slice((params.page() - 1) * params.count(), params.page() * params.count());

            params.total(orderedData.length); // set total for recalc pagination
            $defer.resolve($scope.users);
        }
    });
  })
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<script src="//cdn.jsdelivr.net/angular.ngtable/0.3.3/ng-table.js"></script>
<link rel="stylesheet" href="//cdn.jsdelivr.net/angular.ngtable/0.3.3/ng-table.css" />

<div ng-app="tableApp" ng-controller="MyCtrl">
  <table ng-table="tableParams" show-filter="true" class="table">
        <tr ng-repeat="user in $data">
            <td data-title="'Name'" filter="{ 'Name': 'text' }" sortable="'Name'">
                {{user.Name}}
            </td>
            <td data-title="'Date'" filter="{ 'Date': 'text' }" sortable="'Date'">
                {{user.Date | date}}
            </td>
        </tr>
    </table>
</div>
like image 190
boindiil Avatar answered Oct 30 '22 13:10

boindiil