<html>
<head>
    <title>Ng Repeat Start/End Demo</title>
    <script type='text/javascript' src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
    <script type='text/javascript' src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.7/angular.min.js"></script>
    <script type='text/javascript' src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.7/angular-animate.min.js"></script>
    <script type='text/javascript' src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.7/angular-loader.min.js"></script>
    <script type='text/javascript' src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.7/angular-sanitize.min.js"></script>
    <script type='text/javascript' src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.7/angular-cookies.min.js"></script>
    <script type='text/javascript' src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.7/angular-touch.min.js"></script>
    <script type='text/javascript' src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.7/angular-resource.min.js"></script>
    <script type='text/javascript' src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-bootstrap/0.14.3/ui-bootstrap.min.js"></script>
    <script type='text/javascript' src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-bootstrap/0.14.3/ui-bootstrap-tpls.min.js"></script>
    <script type='text/javascript' src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-router/0.2.13/angular-ui-router.min.js"></script>
    <script type='text/javascript' src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui/0.4.0/angular-ui-ieshiv.min.js"></script>
    <script type='text/javascript' src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui/0.4.0/angular-ui.min.js"></script>
    <link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.4/css/bootstrap.css">
    <link rel="stylesheet" type="text/css" href="style.css">
    <script type='text/javascript' src="script.js"></script>
</head>

<body ng-app="myApp">
    <div ui-view="main" class="container-fluid"></div>
    <script type="text/ng-template" id="state1.html">
    <div class="row well">
      <button class="btn btn-default" ng-click="vm.refresh()">Refresh</button>
    </div>
    
  <uib-accordion>
      <uib-accordion-group ng-repeat="grp in vm.items | unique:'groupName' | orderBy:'groupName'" ng-init="state={isOpen: false}"
        is-open="state.isOpen">
          <uib-accordion-heading>
              <span class="cursor-pointer">{{grp.groupName}} <i class="pull-right glyphicon" ng-class="{'glyphicon-chevron-down': state.isOpen, 'glyphicon-chevron-right': !state.isOpen}"></i></span>
          </uib-accordion-heading>
          <table class="table">
              <tr class="item" ng-class-even="'even'" ng-class-odd="'odd'" ng-repeat-start="item in vm.items | filter:{groupName:grp.groupName}">
                  <td>
                      {{ item.market.name }}
                      <button class="btn btn-default" ng-click="vm.showHistory(item)" ng-bind="item.showHistory ? 'Hide History' : 'Show History'" />
                  </td>
                  <td ng-bind="item.runInfo.name"></td>
                  <td ng-bind="item.jobDetails.name"></td>
                  <td ng-bind="item.jobStats.name"></td>
              </tr>
              <tr class="history" ng-class-even="'even'" ng-class-odd="'odd'" ng-repeat-end ng-repeat="history in item.histories" ng-if="item.showHistory">
                  <td></td>
                  <td ng-bind="history.runInfo.name"></td>
                  <td ng-bind="history.jobDetails.name"></td>
                  <td ng-bind="history.jobStats.name"></td>
              </tr>
          </table>
      </uib-accordion-group>
  </uib-accordion>

      </div> 
    </script>
</body>
</html>
(function () {
    angular.module('myApp.services', ['ngResource', 'ngAnimate']);
    angular.module('myApp.controllers', []);
    angular.module('myApp.directives', []);
    angular.module('myApp.filters', []);
    
    var myApp = angular.module('myApp', [
      'myApp.services',
      'myApp.controllers',
      'myApp.directives',
      'myApp.filters',
      'ngSanitize',
      'ui.bootstrap',
      'ui.router',
      'ui']);
      
var uniqueFilter = function () {
    return function (collection, propName) {
        var result = [], keys = [];

        angular.forEach(collection, function (item) {
            var key = item[propName];
            if (keys.indexOf(key) === -1) {
                keys.push(key);
                result.push(item);
            }
        });
        return result;
    };
};

    uniqueFilter.$inject = ['$filter'];
    angular.module('myApp')
        .filter('unique', uniqueFilter);

    var state1Ctrl = function ($timeout, $log, $filter) {
        var vm = this,
          initItems = function () {
              vm.items = [];
              var groups = [ 'Group1', 'Group2', 'Group3', 'Group4', 'Group5', 'Group6', 'Group7', 'Group8', 'Group9'];
              var randItems = Math.floor(Math.random() * 50) + 1
              for (var i = 0; i < randItems; i++) {
                  var item = {
                      name: "Item " + i.toString(),
                      showHistory: false,
                      market: { name: "Market " + i.toString() },
                      runInfo: { name: "RunInfo " + i.toString() },
                      jobDetails: { name: "JobDetails " + i.toString() },
                      jobStats: { name: "JobStats " + i.toString() },
                      groupName: groups[Math.floor(Math.random() * groups.length)],
                      randprop: Math.random()
                  };
                  item.histories = [];
                  var randHist = Math.floor(Math.random() * 3) + 1;
                  for (var j = 0; j < randHist; j++) {
                      var history = {
                          market: { name: "HistMarket " + j.toString() },
                          runInfo: { name: "HistRunInfo " + j.toString() },
                          jobDetails: { name: "HistJobDetails " + j.toString() },
                          jobStats: { name: "HistJobStats " + j.toString() },
                          randprop: Math.random()
                      };

                      // Randomly clear some of the history
                      history.runInfo.name = (Math.floor(Math.random() * 100) + 1) > 30 ? history.runInfo.name : "";
                      history.jobDetails.name = (Math.floor(Math.random() * 100) + 1) > 50 ? history.jobDetails.name : "";
                      history.jobStats.name = (Math.floor(Math.random() * 100) + 1) > 50 ? history.jobStats.name : "";

                      item.histories.push(history);
                  }
                  vm.items.push(item);
              }
          },
          init = function () {
              $timeout(function () {
                  setTimeout(initItems(), 1000)
              }, 0);
          };

        vm.refresh = function() {
          initItems();
        };
        
        vm.showHistory = function (item) {
            item.showHistory = !item.showHistory;
        };
        
        vm.toggleAll = function () {
          angular.forEach(vm.items, function(item) {
            item.showHistory = !item.showHistory;
          });
        }

        init();
    };

    state1Ctrl.$inject = ['$timeout', '$log', '$filter'];
    angular.module('myApp.controllers')
      .controller('state1Ctrl', state1Ctrl);

    myApp.config(['$locationProvider', '$stateProvider', '$urlRouterProvider',

        function ($locationProvider, $stateProvider, $urlRouterProvider) {

            $locationProvider.html5Mode(false);

            $urlRouterProvider.when('/', '/state1')
                .otherwise("/state1");

            $stateProvider.state('app', {
                abstract: true,
                url: '/',
                views: {
                    'main': {
                        template: '<div ui-view>/div>'
                    }
                }
            })
            .state('app.state1', {
                url: 'state1',
                templateUrl: 'state1.html',
                controller: 'state1Ctrl',
                controllerAs: 'vm',
                reloadOnSearch: false
            })
        }]);

    myApp.run(['$log', function ($log) {
        $log.log("Start.");
    }]);
})()
multiselect {
    display: block;
}

    multiselect > .btn-group {
        min-width: 180px;
    }

    multiselect .btn {
        width: 100%;
        background-color: #FFF;
    }

        multiselect .btn.has-error {
            border: 1px solid #a94442 !important;
            color: #db524b;
        }

    multiselect .dropdown-menu {
        max-height: 300px;
        min-width: 200px;
        overflow-y: auto;
    }

        multiselect .dropdown-menu .filter > input {
            width: 99%;
        }

        multiselect .dropdown-menu .filter .glyphicon {
            cursor: pointer;
            pointer-events: all;
        }

    multiselect .dropdown-menu {
        width: 100%;
        box-sizing: border-box;
        padding: 2px;
    }

    multiselect > .btn-group > button {
        padding-right: 20px;
    }

        multiselect > .btn-group > button > .caret {
            border-left: 4px solid transparent;
            border-right: 4px solid transparent;
            border-top: 4px solid black;
            right: 5px;
            top: 45%;
            position: absolute;
        }

    multiselect .dropdown-menu > li > a {
        padding: 3px 10px;
        cursor: pointer;
    }

        multiselect .dropdown-menu > li > a i {
            margin-right: 4px;
        }

.glyphicon-none:before {
    content: "\e013";
    color: transparent !important;
}

.item.odd {
   background-color: #f9f9f9;
}

.item:hover {
   background-color: #f5f5f5;
}


.history.odd {
   background-color: #bfccdd;
}

.history.even {
   background-color: #a7b4c5;
}

.history:hover
{
  background-color: #99a4b2;
}

.group {
  font-size:1.4em;
  font-weight: bolder;
}
}
This demo shows how to use ng-repeat-start and ng-repeat-end to generate a table with parent/child information.