In this article I will explain with an example, how to implement Nested HTML Table with Expand Collapse in ASP.Net MVC Razor.
The Nested HTML Table will be a combination of Parent – Child Table where Child Tables will be placed inside the Parent Table and the Child Table will be shown and hidden using Expand-Collapse feature in ASP.Net MVC Razor.
The Nested Tables will be populated from database using Entity Framework and the Expand-Collapse feature will be implemented using jQuery.
 
 
Database
Here I am making use of Microsoft’s Northwind Database. You can download it from here.
 
 
Entity Framework Model
Once the Entity Framework is configured and connected to the database table, the Model will look as shown below.
Note: For beginners in ASP.Net MVC and Entity Framework, please refer my article ASP.Net MVC: Simple Entity Framework Tutorial with example. It covers all the information needed for connecting and configuring Entity Framework.
 
Implement Nested Table with Expand Collapse in ASP.Net MVC
 
 
Model
The following Model class consists of three properties.
public class CustomerModel
{
    public string ContactName { get; set; }
    public string City { get; set; }
    public List<Order> Orders { get; set; }
}
 
 
Controller
The Controller consists of the following Action method.
Action method for handling GET operation of Index View
The Entity Framework is now configured and hence now we can create a Controller and write code to fetch the records from the Customers Table of the Northwind Database.
Inside the Index Action method, the Customer records are fetched using Entity Framework and a loop is executed over the fetched records.
Inside the loop, the values of ContactName, City and the List of Orders for each Customer is assigned to an object of CustomerModel class and the object is added to a List of CustomerModel class.
Finally, the List of CustomerModel class are returned to the View.
public class HomeController : Controller
{
    // GET: Home
    public ActionResult Index()
    {
        using (NorthwindEntities entites = new NorthwindEntities())
        {
            List<CustomerModel> model = new List<CustomerModel>();
            foreach (Customer customer in entites.Customers.Take(10))
            {
                model.Add(new CustomerModel
                {
                    ContactName = customer.ContactName,
                    City = customer.City,
                    Orders = entites.Orders.Where(o => o.CustomerID == customer.CustomerID).Take(5).ToList()
                });
            }
 
            return View(model);
        }
    }
}
 
 
View
Inside the View, the CustomerModel class is declared as IEnumerable which specifies that the Model will be available as a Collection.
Populating the Nested Tables
For displaying the Parent Table records, an HTML Table is used. A loop will be executed over the Model which will generate the HTML Table rows with the CustomerModel objects.
The first Cell of the HTML Table contains an IMG element and an HTML DIV. The HTML DIV is hidden and it consists of the Child HTML Table which is generated by executing loop over the List of Orders of each CustomerModel object.
 
Showing Hiding Child Table with Expand-Collapse feature
Each HTML IMG element with Plus image has been assigned a jQuery Click event handler. When the IMG element is clicked, the contents of Child HTML Table are copied from the HTML DIV and are appended to the Parent HTML Table in a new Row.
And the Plus image is replaced with Minus image.
In similar way, each HTML IMG element with Minus image has been assigned a jQuery Click event handler. When the IMG element is clicked, the new HTML Table Row which was appended with the Child Table is removed.
And the Minus image is replaced with Plus image.
@using Nested_Table_MVC.Models
@model IEnumerable<CustomerModel>
 
@{
    Layout = null;
}
 
<!DOCTYPE html>
 
<html>
<head>
    <meta name="viewport" content="width=device-width"/>
    <title>Index</title>
    <style type="text/css">
        body { font-family: Arial; font-size: 10pt; }
        .Grid { border: 1px solid #ccc; border-collapse: collapse; background-color: #fff; }
        .Grid th { background-color: #B8DBFD; color: #333; font-weight: bold; }
        .Grid th, .Grid td { padding: 5px; border: 1px solid #ccc; }
        .Grid img { cursor:pointer; }
        .ChildGrid { width: 100%; }
        .ChildGrid th { background-color: #6C6C6C; color: #fff; font-weight: bold; }
    </style>
</head>
<body>
    <table cellpadding="0" cellspacing="0" class="Grid">
        <tr>
            <th></th>
            <th>Contact Name</th>
            <th>City</th>
        </tr>
        @foreach (CustomerModel customer in Model)
        {
            <tr>
                <td>
                    <img src="~/Images/plus.png"/>
                    <div style="display:none">
                        <table cellpadding="0" cellspacing="0" class="ChildGrid">
                            <tr>
                                <th>OrderID</th>
                                <th>OrderDate</th>
                            </tr>
                            @foreach (Order order in customer.Orders)
                            {
                                <tr>
                                    <td>@order.OrderID</td>
                                    <td>@order.OrderDate.Value.ToShortDateString()</td>
                                </tr>
                            }
                        </table>
                    </div>
                </td>
                <td>@customer.ContactName</td>
                <td>@customer.City</td>
            </tr>
        }
    </table>
    <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
    <script type="text/javascript">
        //Assign Click event to Plus Image.
        $("body").on("click", "img[src*='plus.png']", function () {
            $(this).closest("tr").after("<tr><td></td><td colspan = '999'>" + $(this).next().html() + "</td></tr>");
            $(this).attr("src", "/images/minus.png");
        });
        //Assign Click event to Minus Image.
        $("body").on("click", "img[src*='minus.png']", function () {
            $(this).attr("src", "/images/plus.png");
            $(this).closest("tr").next().remove();
        });
    </script>
</body>
</html>
 
 
Screenshot
Implement Nested Table with Expand Collapse in ASP.Net MVC
 
 
Downloads