How to make HTML table expand on click using JavaScript ?

The expandable table can be achieved by using JavaScript with HTML. By Clicking on a row of the table, it expands and a sub-table pops up. When the user again clicks on that row the content will hide. This can be very useful when the data is complex but it is inter-related.

Example 1: The following example is implemented using HTML, CSS, and JQuery. It shows data of multiple people working in an organization about their age, salary, and job. By clicking on the row, the table expands and the description about that particular employee is displayed.

html

filter_none

edit
close

play_arrow

link
brightness_4
code

<!DOCTYPE html>
<html>
  
<head>
    <script src=
    </script>
    <script src=
    </script>
    <link rel="stylesheet" href=
    <link rel="stylesheet" 
        type="text/css" href=
  
    <script type="text/javascript">
        function showHideRow(row) {
            $("#" + row).toggle();
        }
    </script>
  
    <style>
        body {
            margin: 0 auto;
            padding: 0px;
            text-align: center;
            width: 100%;
            font-family: "Myriad Pro", 
                "Helvetica Neue", Helvetica, 
                Arial, Sans-Serif;
        }
  
        #wrapper {
            margin: 0 auto;
            padding: 0px;
            text-align: center;
            width: 995px;
        }
  
        #wrapper h1 {
            margin-top: 50px;
            font-size: 45px;
            color: #585858;
        }
  
        #wrapper h1 p {
            font-size: 20px;
        }
  
        #table_detail {
            width: 500px;
            text-align: left;
            border-collapse: collapse;
            color: #2E2E2E;
            border: #A4A4A4;
        }
  
        #table_detail tr:hover {
            background-color: #F2F2F2;
        }
  
        #table_detail .hidden_row {
            display: none;
        }
    </style>
</head>
  
<body>
    <div id="wrapper">
  
        <table border=1 id="table_detail" 
            align=center cellpadding=10>
  
            <tr>
                <th>Name</th>
                <th>Age</th>
                <th>Salary</th>
                <th>Job</th>
            </tr>
  
            <tr onclick="showHideRow('hidden_row1');">
                <td>Person-1</td>
                <td>24</td>
                <td>60000</td>
                <td>Computer Programmer</td>
            </tr>
            <tr id="hidden_row1" class="hidden_row">
                <td colspan=4>
                    Person-1 is 24 years old and 
                    he is a computer programmer 
                    he earns 60000 per month
                </td>
            </tr>
  
            <tr onclick="showHideRow('hidden_row2');">
                <td>Person-2</td>
                <td>25</td>
                <td>100000</td>
                <td>Web Designer</td>
            </tr>
            <tr id="hidden_row2" class="hidden_row">
                <td colspan=4>
                    Person-2 is 25 years old and 
                    she is a web designer she earns 
                    100000 per month
                </td>
            </tr>
  
            <tr onclick="showHideRow('hidden_row3');">
                <td>Person-3</td>
                <td>35</td>
                <td>90000</td>
                <td>Cyber Security Expert</td>
            </tr>
            <tr id="hidden_row3" class="hidden_row">
                <td colspan=4>
                    Person is 35 years old and he 
                    is a cyber security expert he 
                    earns 90000 per month
                </td>
            </tr>
  
            <tr onclick="showHideRow('hidden_row4');">
                <td>Person-4</td>
                <td>52</td>
                <td>200000</td>
                <td>Content Writer</td>
            </tr>
            <tr id="hidden_row4" class="hidden_row">
                <td colspan=4>
                    Person-4 is 52 years old and he 
                    is a content writer he earns 
                    200000 per month
                </td>
            </tr>
  
            <tr onclick="showHideRow('hidden_row5');">
                <td>Person-5</td>
                <td>38</td>
                <td>400000</td>
                <td>Chief Executive</td>
            </tr>
            <tr id="hidden_row5" class="hidden_row">
                <td colspan=4>
                    Person-5 is 38 years old and he 
                    is chief executive he earns 
                    400000 per month
                </td>
            </tr>
        </table>
    </div>
</body>
  
</html>

chevron_right


Output:

Example 2: The following example is implemented using HTML, CSS, and JQuery. In this table, profit and loss are displayed for multiple hotels. By clicking on any of the plus signs, a sub-table is displayed which informs about the hotel’s revenue in three different cities.

html

filter_none

edit
close

play_arrow

link
brightness_4
code

<!DOCTYPE html>
<html>
  
<head>
    <title>Expandable Table</title>
  
    <script src=
    <script src=
    <link rel="stylesheet" href=
    <link rel="stylesheet" 
        type="text/css" href=
    <div align="center" class=
        "table table-responsive">
        <table id="ExpenseTable" 
            class="table table-responsive 
            table-hover table-bordered">
        </table>
    </div>
  
    <style>
        .add-btn {
            color: green;
            cursor: pointer;
            margin-right: 6px;
        }
    </style>
</head>
  
<body>
    <script>
        class CellEntry {
            constructor() {
                this.sum = 0;
                this.percentage = 0;
            }
        }
  
        class OutletBasedRowEntry {
            constructor() {
                this.cells = {
                    Total: new CellEntry()
                };
                this.childRows = {};
            }
            add(entry) {
                this.cells.Total.sum += entry.netamount;
                this.getOrCreateCellById(
                    entry.outlet).sum += entry.netamount;
            }
            getOrCreateChildRowById(id) {
                if (!this.childRows[id]) 
                    this.childRows[id] = 
                        new OutletBasedRowEntry();
                return this.childRows[id];
            }
            getOrCreateCellById(id) {
                if (!this.cells[id]) 
                    this.cells[id] = new CellEntry();
                return this.cells[id];
            }
        }
  
        function tabulizeData(data) {
            let TotalRowEntry = new OutletBasedRowEntry();
            data.forEach(entry => {
                TotalRowEntry.add(entry);
                TotalRowEntry.getOrCreateChildRowById(
                        entry.brandname).add(entry);
                TotalRowEntry.getOrCreateChildRowById(
                        entry.brandname).
                        getOrCreateChildRowById(
                        entry.itemname).add(entry);
            });
            renderTable(TotalRowEntry);
        }
  
        function renderTable(TotalRowEntry) {
            let $table = $('#ExpenseTable');
            let $thead = $(
'<thead><tr><th>Brand Name</th></tr><tr><th></th></tr><tr><th>Total</th></tr><thead>'),
                $tbody = $('<tbody>');
            let $headingRows = $thead.find('tr');
  
            function addCellEntriesToRow(
                rowEntry, $row) {
                for (let cellName in 
                    TotalRowEntry.cells) {
                    let cellEntry = rowEntry
                        .getOrCreateCellById(cellName);
                    $('<td>').html(cellEntry.sum)
                            .appendTo($row);
                    $('<td>').html(cellEntry.percentage)
                                .appendTo($row);
                }
            }
  
            $.each(TotalRowEntry.cells, 
                function (cellName, cellEntry) {
                $('<th colspan=2>').html(cellName)
                    .appendTo($headingRows.eq(0));
                $('<th>PROFIT</th>')
                    .appendTo($headingRows.eq(1));
                $('<th>LOSS</th>').appendTo(
                    $headingRows.eq(1));
                $('<th>').html(cellEntry.sum)
                    .appendTo($headingRows.eq(2));
                $('<th>').html(cellEntry.percentage)
                    .appendTo($headingRows.eq(2));
            });
  
            $.each(TotalRowEntry.childRows, 
                function (brandName, rowEntry) {
                let $row = $('<tr>').appendTo($tbody);
                let rowId = 'row' + $row.index();
                let firstCell = $(
'<td><i class="fas fa-plus add-btn" data-toggle="collapse" data-target=".' 
                    + rowId + '"></i>' + brandName 
                    + '</td>').appendTo($row);
                addCellEntriesToRow(rowEntry, $row);
                $.each(rowEntry.childRows, function (
                        itemName, rowEntry) {
                    $row = $('<tr>').addClass('collapse ' 
                        + rowId).appendTo($tbody);
                    $('<td>').html(itemName).appendTo($row);
                    addCellEntriesToRow(rowEntry, $row);
                });
            });
  
            $thead.appendTo($table);
            $tbody.appendTo($table);
        }
  
        tabulizeData([{
            "outlet": "MUMBAI",
            "brandname": "HOTEL-1",
            "itemname": "Restaurant",
            "transactionType": "TransferIn",
            "netamount": 980
        },
        {
            "outlet": "MUMBAI",
            "brandname": "HOTEL-1",
            "itemname": "Hall",
            "transactionType": "TransferIn",
            "netamount": 130
        },
        {
            "outlet": "MUMBAI",
            "brandname": "HOTEL-1",
            "itemname": "Bakery",
            "transactionType": "TransferIn",
            "netamount": 500
        },
        {
            "outlet": "MUMBAI",
            "brandname": "HOTEL-2",
            "itemname": "Restaurant",
            "transactionType": "TransferIn",
            "netamount": 110
        },
        {
            "outlet": "MUMBAI",
            "brandname": "HOTEL-2",
            "itemname": "Party",
            "transactionType": "TransferIn",
            "netamount": 720
        },
        {
            "outlet": "MUMBAI",
            "brandname": "HOTEL-2",
            "itemname": "Pool",
            "transactionType": "TransferIn",
            "netamount": 40000
        },
        {
            "outlet": "MUMBAI",
            "brandname": "HOTEL-2",
            "itemname": "Bakery",
            "transactionType": "TransferIn",
            "netamount": 14000
        },
        {
            "outlet": "MUMBAI",
            "brandname": "HOTEL-2",
            "itemname": "Marriage",
            "transactionType": "TransferIn",
            "netamount": 500
        },
        {
            "outlet": "MUMBAI",
            "brandname": "HOTEL-2",
            "itemname": "Car Valet",
            "transactionType": "TransferIn",
            "netamount": 5500
        },
        {
            "outlet": "MUMBAI",
            "brandname": "HOTEL-2",
            "itemname": "Expense",
            "transactionType": "TransferIn",
            "netamount": 1000
        },
        {
            "outlet": "MUMBAI",
            "brandname": "HOTEL-3",
            "itemname": "Restaurant",
            "transactionType": "TransferIn",
            "netamount": 324
        },
        {
            "outlet": "MUMBAI",
            "brandname": "HOTEL-4",
            "itemname": "Party",
            "transactionType": "LOSS",
            "netamount": 476426
        },
        {
            "outlet": "JAIPUR",
            "brandname": "HOTEL-4",
            "itemname": "Party",
            "transactionType": "LOSS",
            "netamount": 115313
        },
        {
            "outlet": "BANGALORE",
            "brandname": "HOTEL-4",
            "itemname": "Party",
            "transactionType": "LOSS",
            "netamount": 92141
        }
        ]);
    </script>
</body>
  
</html>

chevron_right


Output:

full-stack-img




My Personal Notes arrow_drop_up

Check out this Author's contributed articles.

If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.

Please Improve this article if you find anything incorrect by clicking on the "Improve Article" button below.