Angularjs group data from a field in the records

Problem

Is there group by like something in angular that can convert this sort of json data grouped under group_header.

outer list to sort data by groups and then inner list data items of that group, i couldn't make sense of this if this data can be grouped?

var data = [  
   {  
      "id":23,
      "name":"Fun Run (Pre-Registration Required)",
      "date":"Wednesday Nov 12",
      "group_header":"Sessions from 7:00 am to 1:45 pm"
   },
   {  
      "id":24,
      "name":"Breakfast",
      "date":"Wednesday Nov 12",
      "group_header":"Sessions from 7:00 am to 1:45 pm"
   },
   {  
      "id":25,
      "name":"Opening Address",
      "date":"Wednesday Nov 12",
      "group_header":"Sessions from 7:00 am to 1:45 pm"
   },
   {  
      "id":25,
      "name":"abc",
      "date":"Wednesday Nov 12",
      "group_header":"Sessions from 1:00 pm to 9:00 pm"
   },
   {  
      "id":26,
      "name":"xyz",
      "date":"Wednesday Nov 12",
      "group_header":"Sessions from 1:00 pm to 9:00 pm"
   },
    {  
      "id":26,
      "name":"xyz",
      "date":"Wednesday Nov 12",
      "group_header":"Sessions from 8:45 am to 2:00 pm" //notice a different header
   },
  {  
      "id":26,
      "name":"xyz",
      "date":"Wednesday Nov 12",
      "group_header":"Sessions from 1:30 pm to 11:00 pm" //another different header
   }
]
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>

<ul>
    <li>Sessions from 7:00 am to 1:45 pm
        <ul>
            <li>Fun Run (Pre-Registration Required)</li>
            <li>Breakfast</li>
            <li>Opening Address</li>
        </ul>
    </li>
    <li>Sessions from 1:00 pm to 9:00 pm
        <ul>
            <li>abc</li>
            <li>xyz Address</li>
        </ul>
    </li>
    <li>another custom header (no pattern to it) - sessions from 10 am to 5 pm 
        <ul>
            <li>abc</li>
            <li>xyz Address</li>
        </ul>
    </li>
</ul>

Problem courtesy of: user2727195

Solution

Custom filter option is written now at the end if you wanted to create more complex filtering.

First EDIT: Using Angular-Filter from angular-filter GitHub

Working JSBIN as your Request I'm using angular-filter, group-by option, which allows me to do so. you could follow html witch is rather simple understand

HTML:

<ul ng-repeat="(key, value) in data | groupBy: 'group_header'"> //First extracting key value, from ng-repeat and grouping it by group_header ( External 3rd party filter by angular-filter).

  Group name: {{ key }}
  <li ng-repeat="item in value"> // Then extra ng-repeat to iterate each of the objects and presenting the name .
    Activity : {{ item.name }} 
  </li>
</ul>

JS: All you have to do:

Inject angular-filter to your code like so:

angular.module('app',['angular.filter'])..

So I've written a filter for your purpose which supposed to be tailor made , but it's also, reusable and easy to test as well.

Before you jump into COPY & PASTE:

It's important for you to understand why to use filters , and how to use them well.

In my solution I've written a filter which you can declare a minHour and it will show only the hours that are later than that hour.

let's read the code:

app.filter('minHour',function(){ // 1 - Explained below.
  return function(items, minHour){ //2 - Explained below.
    var filtered = [];
    for(var i =0 ; i < items.length ; i ++){
        var hour = parseInt(items[i].start.slice(0,2)); //3 - Explained below.
        if(hour === minHour || hour > minHour){
          filtered.push(items[i]);
        }
    }
    return filtered;
  }
})

I find most of the code above rather easy to read, but I am writing explanation on the difficault bits:

1) This is how angular defines a new filter.

2) The filter will always return a function with argument, the first argument is ALWAYS the items of the ng-repeat, the second argument is ALWAYS the string that will be used when you call the filter. (This is the most important thing here).

3) This is working BUT warning this is a BAD PRACTICE I assume too many things in the function!

*I assumed that the hour will be written in the first two letters of the string.

*I assumed that the hour will always be on "start" property without checking the attribute first.

*I assumed that I could compare those values.

So lessons learned:

Before writing a filter, please make sure that you are not making too many assumptions.

Always test the honesty of the data before!

Usage + Plunker:

<ul>
  <li ng-repeat="items in data | minHour:09">{{items.start}}</li>
</ul>

Plunker

I didn't write the max hour filter, because I really wanted you to practice it. It's really easy if you read my answer through.

If you have more questions I'd be happy to help!

Solution courtesy of: Linial

Discussion

You could use the angular-filter like this:

In your HTML head:

<script src="//cdnjs.cloudflare.com/ajax/libs/angular-filter/0.4.7/angular-filter.js">    </script>.

Then in your angular app declare the 'angular.filter':

angular.module('project', ['ngRoute','angular.filter']).config(fu....

Then utilize like:

<tr ng-repeat="(k,v) in data| groupBy: 'group_header'">
    <td>{{k}}</td>
    <td>
        <ul>
            <li ng-repeat="item in v">
                {{item.name}}
            </li>
        </ul>
    </td>
</tr>
Discussion courtesy of: Coldstar

This recipe can be found in it's original form on Stack Over Flow.