Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Splitting ng-repeat every 3 items

Using AngularJS, I'm iterating over a JSON object containing an array of event objects, containing an array of competition objects.

I wish to show each event in a table, and then each competition in a td, but only three cells per row

I'm using ng-repeat to return a list of tables for each event, but I'm having trouble with splitting the competitions into a new <tr> every three <td>s

Aside from rebuilding my own massive object from the JSON, what is the best way to do what I'm describing in Angular?


Current view:

<table ng-repeat="listing in listings">
    <tr>
        <th colspan="3">{{listing.name}}</th>
    </tr>
    <tr>
        <td ng-repeat="competition in listing.competitions">
            {{competition.id}} - {{competition.name}}
        </td>
    </tr>
</table>

Desired output:

<table>
    <tr>
        <th colspan="3">Event Name</th>
    </tr>
    <tr>
        <td>competition id - competition name</td>
        <td>competition id - competition name</td>
        <td>competition id - competition name</td>
    </tr>
    <tr>
        <td>competition id - competition name</td>
        <td>competition id - competition name</td>
        <td>competition id - competition name</td>
    </tr>
</table>

Controller:

app.controller('EventsCtrl', function ($scope, $http) {
  $scope.loading = true;

  $http.get('scripts/JSON/events.json').then(function (response) {
    var listings = response['data'].events;

    $scope.listings = listings;
  });
});

events.json

{
"events": [
    {
        "id": 418,
        "name": "et ullamco",
        "competitions": [
            {
                "id": 933,
                "name": "qui in deserunt occaecat et",
                "startTime": 1381092189
            },
            {
                "id": 853,
                "name": "eu enim ex incididunt do",
                "startTime": 1380708266
            },
            {
                "id": 5738,
                "name": "ad est ut aliquip et",
                "startTime": 1381366623
            },
            {
                "id": 7599,
                "name": "sit ex voluptate aliqua dolor",
                "startTime": 1381284106
            },
            {
                "id": 7481,
                "name": "laborum consequat deserunt do aliqua",
                "startTime": 1380874273
            },
            {
                "id": 3441,
                "name": "amet reprehenderit sint sunt proident",
                "startTime": 1380554850
            },
            {
                "id": 1959,
                "name": "ullamco minim minim in voluptate",
                "startTime": 1380651981
            }
        ]
    },
like image 752
Coogie Avatar asked Oct 13 '13 16:10

Coogie


People also ask

How do you condition in NG-repeat?

You can add condition using ng-if also and this is effective too. You can apply any condition to your list using ng-if attribute. In below example, I have put condition where Age > 20 and IsActive is true. ng-repeat will fetch all records which full fill this scenario.

How do you use two ng-repeat in a table?

You can nest two ng-repeat together in order to create a more complex table. The first ng-repeat in the tr tag will create the rows and the second one in the td tag will create one column per element in the collection.

Does ng-repeat create a new scope?

Each iteration of ng-repeat creates a new child scope, and that new child scope always gets a new property.

How do I create an index in NG-repeat?

Note: The $index variable is used to get the Index of the Row created by ng-repeat directive. Each row of the HTML Table consists of a Button which has been assigned ng-click directive. The $index variable is passed as parameter to the GetRowIndex function.


1 Answers

You are using a table but the semantics of your data indicate you have a list of lists. You should consider outputting this with <ul><li> instead of a grid.

<ul ng-repeat="listing in listings">
    <li>
        <h2>{{listing.name}}</h2>
        <ul ng-repeat="competition in listing.competitions">
            <li>
              {{competition.id}} - {{competition.name}}
            </li>
        </ul>
    </li>
</ul>

You can achieve your desired layout with CSS quite easily using the above HTML. Checkout the "block grids" in Twitter Bootstrap or Foundation for examples. Tables should generally be used only for data that is actually tabular.

However...

You're question does still bear answering since there may be other reasons to alternate templates in the way you suggest. You could use a function for this to get things three at a time:

<table ng-repeat="listing in listings">
    <tr>
        <th colspan="3">{{listing.name}}</th>
    </tr>
    <tr ng-repeat="group in competitions">
        <td ng-repeat="competition in group">
            {{competition.id}} - {{competition.name}}
        </td>
    </tr>
</table>

In your controller you can create a "list of lists" to bind to the nested repeaters

// Adapted from Fresheyeball's solution

$scope.competitions = []
compSet = []
for(var i; i < $scope.listings.competitions; i++){
   var competition = $scope.listings.competitions[i];
   if( i % 3 ){
      $scope.competitions.push(compSet);
      compSet = [];
   }
   compSet.push(competition);
}
like image 194
Chris Nicola Avatar answered Nov 02 '22 07:11

Chris Nicola