2

I am trying to groupBy a date which is a JS date object. I want to group the data per day.
Any ideas how I can do this in a view?

$scope.data = {
  messages: [
    {
      date: new Date(1432811030 * 1000),
      message: 'Some text 01'
    },
    {
      date: new Date(1432731600 * 1000),
      message: 'Some text 02'
    },
    {
      date: new Date(1432819703 * 1000),
      message: 'Some text 03'
    }
  ]
};

And in my view I use:

<div ng-repeat="(key, value) in data.messages | groupBy: 'date'">
  <div>{{ key }}</div>
  <div ng-repeat="message in value">
    <div>{{ message.message }}</div>
  </div>
</div>

I have this angular.filter module included in mu project: https://github.com/a8m/angular-filter

Problem is that I now group per date/time instead of per day. Any idea how?

a8m
  • 9,334
  • 4
  • 37
  • 40
Mark Veenstra
  • 4,691
  • 6
  • 35
  • 66

2 Answers2

6

DEMO: http://plnkr.co/edit/djPMu4UH9t9BeGwBcUMI

Screenshot: https://www.dropbox.com/s/9z5t6nsp3x1266s/Screenshot%202015-05-28%2019.50.44.png?dl=0

HTML:

<body ng-app="myApp" ng-controller="myController">
  <div ng-repeat="(key, value) in testData.messages">
    <div>{{ key }}</div>
    <div ng-repeat="message in value">
      <div>{{ message }}</div>
    </div>
  </div>
</body>

JS:

var app = angular.module('myApp', []);
app.controller('myController', function($scope) {

  $scope.data = {
    messages: [
      {
        date: new Date(1432811030 * 1000),
        message: 'Some text 01'
      },
      {
        date: new Date(1432731600 * 1000),
        message: 'Some text 02'
      },
      {
        date: new Date(1432819703 * 1000),
        message: 'Some text 03'
      }
    ]
  };


  $scope.convertTo = function (arr, key, dayWise) {
    var groups = {};
    for (var i=0;l= arr.length, i<l;i++) {
      if (dayWise) {
        arr[i][key] = arr[i][key].toLocaleDateString();
      }
      else {
        arr[i][key] = arr[i][key].toTimeString();
      }
      groups[arr[i][key]] = groups[arr[i][key]] || [];
            groups[arr[i][key]].push(arr[i]);
    }
    return groups;
    };

     $scope.testData = {};
     angular.copy($scope.data, $scope.testData);

    $scope.testData.messages = $scope.convertTo($scope.testData.messages, 'date', true);
    console.log($scope.testData)

});
softvar
  • 17,917
  • 12
  • 55
  • 76
  • Please see my updated code and demo, easy to toggle date/time filter without changing the original data object. – softvar May 28 '15 at 14:21
  • I also came up same solution when i faced this issue. But now i am facing different requirment. Imagine you have filter associated with this line **
    ** when there no entry in some filtered category, i want to hide that category text. like i want to hide **key** when value list is empty after filter
    – Saravanan Jan 02 '17 at 07:00
4

There are two approaches here. One is to use a group by. The other which is what I'd go for is to pre-group my data by day, and have a "dumb" view which doesn't do the grouping but instead the grouping is done in a service beforehand or at the least in the controller. I'd add a plunkr to demonstrate.

http://plnkr.co/edit/z1Y4147sCw2cCAfunHwg?p=preview

If you have your data like that:

vm.data = [
    {day: new Date(1432811030000), msg: 'someText'}, 
    {day: new Date(1432811030000), msg: 'someText2'},
    {day: new Date(1432811030000), msg: 'someText3'},
    {day: new Date(1432731600000), msg: 'someTextDay2'},
    {day: new Date(1432731600000), msg: 'someTextDay2-1'}, 
    {day: new Date(1432731600000), msg: 'someTextDay2-2'},
    {day: new Date(1432819703000), msg: 'someTextDay3'},
    {day: new Date(1432819703000), msg: 'someTextDay3'}
  ];

Here is the relevant code:

 <ul data-ng-repeat="(key, val) in vm.data | groupBy: 'day'">
      Day: {{key}}
      <li data-ng-repeat="msg in val">
         {{msg.msg}}
      </li>
  </ul>

And, if on the other hand, you were to pre-group your data, your relevant code in your view would look like this:

<ul data-ng-repeat="(key, val) in vm.groupedData">
   Day: {{key}}
   <li data-ng-repeat="msg in val">
      {{msg.msg}}
   </li>
</ul>

and here is the js code that groups them per day:

 var groupByDate = function groupByDate(messages){
      var grouped = {};
      _.forEach(messages, function(msg){
          var actualDay = new Date(msg.day - (msg.day % 86400000));
          if ( !grouped[actualDay] ){
            grouped[actualDay] = [];
          }
          grouped[actualDay].push(msg);
      });

      return grouped;
  };
Community
  • 1
  • 1
Nikola Yovchev
  • 9,498
  • 4
  • 46
  • 72