nickponline
nickponline

Reputation: 25914

How do I create a new row inside an angular ng-repeat?

I have an ng-repeat creating rows, and I want to insert a new row periodically, but the logic for creating this is inside the row and ends up messing up the nesting, for example:

  <tr ng-repeat='item in items'>

       <!-- this doesn't work well -->
       <tr ng-if='items[$index].day != items[$index-1].day'>
       <td colspan=2>
       NEW DAY
       </td>
       </tr>

       <td>{{item.name}}</td>
       <td>{{item.day}}</td>

    </tr>

I want the "day divider" rows amongst the data rows whenever the day changes.

Upvotes: 2

Views: 2889

Answers (6)

Ivin Raj
Ivin Raj

Reputation: 3429

You can use repeat-start and repeat-end:

<tr ng-repeat-start="item in items">
       <td>{{item.name}}</td>
       <td>{{item.day}}</td>
    </tr>
  <tr ng-repeat-end> 
    <td colspan="2">
</tr>

Upvotes: 0

Ivin Raj
Ivin Raj

Reputation: 3429

Plz try this one

   <body ng-app="ngAnimate">
  Click me: <input type="checkbox" ng-model="checked" aria-label="Toggle ngHide"><br/>
<div>
  Show:
  <div class="check-element animate-show" ng-show="checked">
    <span class="glyphicon glyphicon-thumbs-up"></span> I show up when your checkbox is checked.
  </div>
</div>
<div>
  Hide:
  <div class="check-element animate-show" ng-hide="checked">
    <span class="glyphicon glyphicon-thumbs-down"></span> I hide when your checkbox is checked.
  </div>
</div>
</body>

Demo

Upvotes: 0

nickponline
nickponline

Reputation: 25914

This works although it seems gross:

         <tr ng-repeat-start='item in items'>

               <tr ng-if='items[$index].day != items[$index-1].day'>
               <td colspan=2>
               NEW DAY
               </td>
               </tr>



               <td>{{item.name}}</td>
               <td>{{item.day}}</td>

            </tr>

      <!-- dummy row -->
      <tr ng-repeat-end></tr>

Upvotes: 0

casraf
casraf

Reputation: 21684

Sounds like you might want to group the data by days and do two nested repeaters.

angular.module('app', []);
angular.module('app').controller('Ctrl', function($scope) {
  $scope.rows = [
    { name: 'one', day: 'monday' },
    { name: 'two', day: 'monday' },
    { name: 'three', day: 'tuesday' },
    { name: 'four', day: 'tuesday' },
    { name: 'five', day: 'thursday' }
  ];
  
  var groupBy = function(arr, property) { // you can use Underscore instead
    var output = {};
    
    for (var i = 0; i < arr.length; i++) {
      var item = arr[i];
      if (typeof output[item[property]] === 'undefined') {
        output[item[property]] = [];
      }
      if (item.hasOwnProperty(property)) {
        output[item[property]].push(item);
      }
    }
    
    return output;
  };
  
  $scope.groupedRows = groupBy($scope.rows, 'day');
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>

<div ng-app="app">
  <div ng-controller="Ctrl">
    <table>
      <!-- it's valid to have more than one tbody -->
      <tbody ng-repeat="(key, group) in groupedRows">
        <tr>
          <th colspan="2">{{key}}</th>
        </tr>
        <tr ng-repeat="row in group">
          <td>{{row.name}}</td>
          <td>{{row.day}}</td>
        </tr>
      </tbody>
    </table>
  </div>
</div>

Note: if you want the grouped rows to be ordered properly, you might want to store your day as an integer, and only change how it displays. Since you can't "actually" sort object keys, they auto-sort alphabetically in the JS engine, you can have them sorted properly if they are numeric.

Upvotes: 0

David Votrubec
David Votrubec

Reputation: 4156

UPDATE

What about having new method in your controller like isDivider(item) which would return bool value.

I did not test this but it should work:

    <tr ng-repeat='item in items'>

       <td ng-if="isDivider(item)==true" colspan=2>NEW DAY<td>

       <td ng-if="isDivider(item)==false">{{item.name}}</td>
       <td ng-if="isDivider(item)==false">{{item.day}}</td>

    </tr>

Upvotes: 0

Ivin Raj
Ivin Raj

Reputation: 3429

You can use ng-repeat-start and ng-repeat-end as follow:

<tr ng-repeat-start="item in items">
       <td>{{item.name}}</td>
       <td>{{item.day}}</td>
    </tr>
    <tr ng-repeat-end>
       <td>Expand/collapse content</td>
    </tr> 

Demo

Upvotes: 3

Related Questions