8

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>
Nica
  • 177
  • 4
  • 17
user2727195
  • 7,122
  • 17
  • 70
  • 118

2 Answers2

7

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!

Linial
  • 1,154
  • 9
  • 22
  • Sure thing, don't hesitate to ask, to try to see how this code work, just change html minHour to what ever you like. this is pure JavaScript inside filter function. – Linial Nov 10 '14 at 00:40
  • actually I realize something, I really don't have to check for less than some hour, I need to sort out data under headers, I'm gonna delete the start and end fields to avoid the confusion from json, so it's not really checking the hour range, it's a custom header and varies across rows, the good thing is that rows are coming sorted by group_header, – user2727195 Nov 10 '14 at 00:49
  • That would create much less flexibility to the code, since you could have endless number of unique sessions. – Linial Nov 10 '14 at 00:52
  • yes you're right, there's no pattern to those headers, one day they could have only sessions from let's say 10 am to 2 pm, so it's custom for each day, the key is they all are coming as a group, the next rows of groups will have their own unique header, that's why I said something like sql group by in angular – user2727195 Nov 10 '14 at 00:53
  • i saw this post but I can't really understand it, wonder if you can help with that http://stackoverflow.com/questions/19992090/angularjs-group-by-directive – user2727195 Nov 10 '14 at 00:57
  • @user2727195 Edited. look at JSBIN – Linial Nov 10 '14 at 01:13
1

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>
Coldstar
  • 1,324
  • 1
  • 12
  • 32