In this article I will explain with an example, how to use AngularJS nested ng-repeat directive to dynamically populate (bind) nested HTML Table from JSON array.
Nested Tables means Table inside Table and it will be created by nesting one ng-repeat loop inside another ng-repeat loop.
First an array of JSON objects is generated and then it is used to populate (bind) nested HTML Table using the nested AngularJS ng-repeat directive.
 
 
Populate (Bind) dynamic Nested HTML Table from JSON in AngularJS
The below HTML Markup consists of an HTML DIV to which ng-app and ng-controller AngularJS directives have been assigned.
The HTML DIV consists of an HTML Button and Table which will be populated from JSON array using ng-repeat directive.
Note: If you want to learn more about these directives please refer my article Introduction to AngularJS.
 
The Button has been assigned ng-click directive. When the Button is clicked, the GenerateTable function of the Controller gets called.
Note: If you want to learn more about ng-click directive, please refer my article ng-click directive example.
 
Inside the GenerateTable function, an array of JSON objects is created and assigned to the Customers JSON array.
The ng-repeat directive as the name suggests repeats the element based on the length of the collection and in this scenario it will repeat the TR element (HTML Table Row).
The TBODY element of the HTML Table has been assigned ng-repeat directive in order to iterate through all the items of the Customers JSON array.
For each JSON object in the Customers JSON array, a TR element (HTML Table Row) is generated and appended into the HTML Table.
The last cell of the HTML Table Row consists of another nested HTML Table which will populate the Orders for each Customer.
The TBODY element of the nested HTML Table has been assigned ng-repeat directive in order to iterate through all the items of the Orders JSON array.
 For each JSON object in the Orders JSON array, a TR element (HTML Table Row) is generated and appended into the nested HTML Table.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
    <title></title>
</head>
<body>
    <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.9/angular.min.js"></script>
    <script type="text/javascript">
        var app = angular.module('MyApp', [])
        app.controller('MyController', function ($scope) {
            $scope.IsVisible = false;
            $scope.GenerateTable = function () {
                $scope.Customers = [
                {
                    CustomerId: 1, Name: "John Hammond", Country: "United States",
                    Orders: [
                        { OrderId: 10248, Freight: 32.38, ShipCountry: 'France' },
                        { OrderId: 10249, Freight: 12.43, ShipCountry: 'Japan' },
                        { OrderId: 10250, Freight: 66.35, ShipCountry: 'Russia' }
                   ]
                },
                {
                    CustomerId: 2, Name: "Mudassar Khan", Country: "India",
                    Orders: [
                        { OrderId: 10266, Freight: 77.0, ShipCountry: 'Argentina' },
                        { OrderId: 10267, Freight: 101.12, ShipCountry: 'Australia' },
                        { OrderId: 10268, Freight: 11.61, ShipCountry: 'Germany' }
                    ]
                },
                {
                    CustomerId: 3, Name: "Suzanne Mathews", Country: "France",
                    Orders: [{ OrderId: 10250, Freight: 65.83, ShipCountry: 'Brazil'} ]
                },
                {
                    CustomerId: 4, Name: "Robert Schidner", Country: "Russia",
                    Orders: [
                        { OrderId: 10233, Freight: 89.11, ShipCountry: 'Belgium' },
                        { OrderId: 10234, Freight: 51.30, ShipCountry: 'Canada' },
                        { OrderId: 10235, Freight: 46.11, ShipCountry: 'Austria' }
                    ]
                }
               ];
                $scope.IsVisible = true;
            };
        });
    </script>
    <div ng-app="MyApp" ng-controller="MyController">
        <input type="button" value="Generate Table" ng-click="GenerateTable()" />
        <hr />
        <table cellpadding="0" cellspacing="0" ng-show="IsVisible">
            <tr>
                <th>Customer Id</th>
                <th>Name</th>
                <th>Country</th>
                <th>Orders</th>
            </tr>
            <tbody ng-repeat="c in Customers">
                <tr>
                    <td>{{c.CustomerId}}</td>
                    <td>{{c.Name}}</td>
                    <td>{{c.Country}}</td>
                    <td>
                        <table cellpadding="0" cellspacing="0">
                            <tr>
                                <th>Order Id</th>
                                <th>Freight</th>
                                <th>ShipCountry</th>
                            </tr>
                            <tbody ng-repeat="o in c.Orders">
                            <tr>
                                <td>{{o.OrderId}}</td>
                                <td>{{o.Freight}}</td>
                                <td>{{o.ShipCountry}}</td>
                            </tr>
                            </tbody>
                        </table>
                    </td>
                </tr>
            </tbody>
        </table>
    </div>
</body>
</html>
 
 
Screenshot
AngularJS ng-repeat Nested Table: Populate (Bind) dynamic Nested HTML Table from JSON in AngularJS
 
 
Browser Compatibility

The above code has been tested in the following browsers.

Internet Explorer  FireFox  Chrome  Safari  Opera 

* All browser logos displayed above are property of their respective owners.

 
 
Demo
 
 
Downloads