0

I want to display a list of records. The data is a list of objects, each object is like this:

{
  date: "01/01/2001",
  time: "04:28 AM",
  message: "message strings here."
}

I want to display them in the way that grouped by date. Like this:

08/01/2005
 04:28 AM message strings here.
 04:20 AM message strings here.
 02:12 AM message strings here.
07/05/2005
 03:32 PM message strings here.
 02:12 PM message strings here.

This is my code:

<div>{{date}}</div> <!--date is initialized in my angular controller to be the first date in the records.-->
<div ng-repeat="record in records">
    <div ng-if="record.date != date" ng-model="date">{{record.date}}</div> <!--here I expect date would be updated to record.date.-->
    <div>{{record.time}} {{record.message}}</div>
</div>

But I get result like this:

08/01/2005
 04:28 AM message strings here.
 04:20 AM message strings here.
 02:12 AM message strings here.
07/05/2005
 03:32 PM message strings here.
07/05/2005 //This is displayed, means the date is not updated when it reach the first 07/05/2005 above.
 02:12 PM message strings here.

I searched online, a lot of model data binding is to bind model with <input>. But I don't want input tag. And the ng-model in <div> seems doesn't update the model to the text displayed in the <div>. I wonder what's the proper way to achieve this.

Mr Lister
  • 45,515
  • 15
  • 108
  • 150
Carrie
  • 480
  • 3
  • 10
  • 25

2 Answers2

3

I setup an example based on your data on how to do that: https://jsfiddle.net/63o96cf2/

Original answer: https://stackoverflow.com/a/14800865/3298029

View:

<div ng-app ng-controller="Main">
  <ul ng-repeat="group in recordsToFilter() | filter:filterRecords">
    <b>{{group.date}}</b>
    <li ng-repeat="record in records | filter:{date: group.date}">{{record.time}}: {{record.message}}</li>
  </ul>
</div>

Controller:

function Main($scope) {
  $scope.records = [{
    date: "01/01/2001",
    time: "03:28 AM",
    message: "message strings here."
  }, {
    date: "01/01/2001",
    time: "04:28 AM",
    message: "message strings here."
  }, {
    date: "01/01/2001",
    time: "06:28 AM",
    message: "message strings here."
  }, {
    date: "01/01/2002",
    time: "04:28 AM",
    message: "message strings here."
  }, {
    date: "01/01/2002",
    time: "05:28 AM",
    message: "message strings here."
  }];

  var indexedRecords = [];

  $scope.recordsToFilter = function() {
    indexedRecords = [];
    return $scope.records;
  }

  $scope.filterRecords = function(record) {
    var recordIsNew = indexedRecords.indexOf(record.date) == -1;
    if (recordIsNew) {
      indexedRecords.push(record.date);
    }
    return recordIsNew;
  }
}
Community
  • 1
  • 1
d.h.
  • 1,206
  • 1
  • 18
  • 33
  • If that is working for you it would be awesome if you accept this as the correct answer. – d.h. Mar 22 '16 at 22:00
  • Please include the code from that fiddle in the question itself. Without that link, this post does not answer the question. There are companies which block jsfiddle.net, and employees would be out of luck if they ran across your answer. See [answer] for more information. – Heretic Monkey Mar 22 '16 at 22:01
  • You mean in the answer. not the question Mike? I changed it. – d.h. Mar 22 '16 at 22:04
  • Yeah, sorry, My fingers were on automatic. Thanks, that makes this a much better answer, and worthy of an upvote :). – Heretic Monkey Mar 22 '16 at 22:06
  • It works like a charm. One thing I don't understand much though, why do we need the recordsToFilter function, why can't we just pass the records in the html? Is it simply because we need to empty the indexedRecords list every time? – Carrie Mar 22 '16 at 22:08
  • Yes. The record grouping is going to be reset each time it is rendered via indexedRecords = []; – d.h. Mar 22 '16 at 22:30
  • The ng-repeat filter is executed a lot and if the indexedRecords is not emptied every time the loop won't display anything. If you need to know whats going on just put some console.log() into the filterRecords function. – d.h. Mar 22 '16 at 23:36
1

You need to use "groupBy" filter in https://github.com/a8m/angular-filter#groupby

HTML

<ul ng-repeat="record in records | groupBy:'date'">
  {{ record.date }}
  <li ng-repeat="player in value">
   {{ record.time }} ... 
  </li>
</ul>
UserNeD
  • 1,409
  • 13
  • 14
  • I got this error: (index):11596 Error: [$injector:unpr] Unknown provider: groupByFilterProvider <- groupByFilter – Carrie Mar 22 '16 at 21:49
  • I think a "groupBy" filter is not supported out of the box in angular. What UserNeD is referring too might be the following extension: https://github.com/a8m/angular-filter which supports several filters. If you are looking for a solution without an extension try my answer. – d.h. Mar 22 '16 at 21:57
  • you have to include angular.filter( github.com/a8m/angular-filter ), because filters like orderBy is available out of the box, but not groupBy. – Yoan Mar 22 '16 at 22:00