Expandable Row with Nested Grid
ZingGrid provides custom HTML, CSS, and JavaScript to easily create a collapsable row with a secondary nested grid in the tree.
Result
Full
HTML
CSS
JS
Edit
Download
⌃
[[record.name]] ([[record.job]])
Full Code
<!DOCTYPE html> <html class="zg-html"> <head> <meta charset="utf-8"> <title>ZingGrid Demo</title> <script nonce="undefined" src="https://cdn.zinggrid.com/zinggrid.min.js"></script> <style> .zg-body { background: #fff; } zing-grid[loading] { height: 500px; } zing-grid zing-grid[loading] { height: 91px; } /** Expandable Row Trigger **/ .zg-body .arrow { display: inline-block; transform: rotate(90deg); transform-origin: 0% 0%; cursor: pointer; font-size: 1.5rem; position: relative; left: 2.5rem; top: 0.25rem; } .zg-body .active .arrow { transform: rotate(180deg); left: 2.5rem; top: 1.5rem; } /** Expandable Row Header **/ .zg-body .row--header { display: flex; align-items: center; } .zg-body .team--info { margin-left: 2.5rem; } /** Expandable Row CSS **/ .zg-body zg-cell[type="custom"] { padding: 0; } .zg-body .default { border-bottom: 1px solid #ebebeb; } .zg-body zg-row:hover { cursor: pointer; background-color: #f5f7fa; transition: background-color 0.25s ease-in; } .zg-body .expandable { background: #f5f5f5; padding: 1rem 0; display: none; position: relative; overflow: hidden; } .zg-body .active .expandable { display: block; } /** Set padding **/ /** NOTE: Css looks off here, but it is to fix how it looks on site **/ .zg-body .default--arrow { padding: 0.9rem 0; } zing-grid[loading] { height: 487px; } </style> </head> <body class="zg-body"> <zing-grid caption="Expandable Rows w/Nested Grid" viewport-stop loading src="https://zinggrid-example-datasets.uc.r.appspot.com/employees"> <zg-colgroup> <zg-column type="custom" header="Employees" renderer="assignDataToNestedGrid"> <template> <div class="row--header"> <div class="default default--arrow"> <span class="arrow">⌃</span> </div> <div class="team--info">[[record.name]] ([[record.job]])</div> </div> <div class="expandable"> <!-- define nested column and types --> <zing-grid width="100%" viewport-stop> <zg-colgroup> <zg-column index="actor"></zg-column> <zg-column index="job"></zg-column> <zg-column index="age" type="number"></zg-column> <zg-column index="hourly_salary" type="currency"></zg-column> <zg-column index="origin"></zg-column> <zg-column index="home_town"></zg-column> <zg-column index="gender"></zg-column> <zg-column index="species"></zg-column> </zg-colgroup> </zing-grid> </div> </template> </zg-column> </zg-colgroup> </zing-grid> <script> ZingGrid.setLicense(['26ccbfec16b8be9ee98c7d57bee6e498']); function assignDataToNestedGrid(index, cellRef, recordRef) { // assign data to secondary zing-grid let zgRef = cellRef.querySelector('zing-grid'); let data = [recordRef.record]; zgRef.setData(JSON.stringify(data)); } // window:load event for Javascript to run after HTML // because this Javascript is injected into the document head window.addEventListener('load', () => { // Javascript code to execute after DOM content const zgRef = document.querySelector('zing-grid'); zgRef.addEventListener('row:click', bindExpandEvent); function bindExpandEvent(e) { let oDOMRow = e.detail.ZGTarget; oDOMRow.classList.toggle('active'); // refresh the grid to properly size all the columns oDOMRow.querySelector('zing-grid').refresh(); } // open first row zgRef.executeOnLoad(() => { setTimeout(function() { const zgFirstRow = document.querySelector('zg-row[aria-rowindex="2"]'); zgFirstRow.classList.toggle('active'); zgFirstRow.querySelector('zing-grid').refresh(); }, 200); }); }); </script> </body> </html>
<!DOCTYPE html> <html class="zg-html"> <head> <meta charset="utf-8"> <title>ZingGrid Demo</title> <script src="https://cdn.zinggrid.com/zinggrid.min.js"></script> </head> <body class="zg-body"> <zing-grid caption="Expandable Rows w/Nested Grid" viewport-stop loading src="https://zinggrid-example-datasets.uc.r.appspot.com/employees"> <zg-colgroup> <zg-column type="custom" header="Employees" renderer="assignDataToNestedGrid"> <template> <div class="row--header"> <div class="default default--arrow"> <span class="arrow">⌃</span> </div> <div class="team--info">[[record.name]] ([[record.job]])</div> </div> <div class="expandable"> <!-- define nested column and types --> <zing-grid width="100%" viewport-stop> <zg-colgroup> <zg-column index="actor"></zg-column> <zg-column index="job"></zg-column> <zg-column index="age" type="number"></zg-column> <zg-column index="hourly_salary" type="currency"></zg-column> <zg-column index="origin"></zg-column> <zg-column index="home_town"></zg-column> <zg-column index="gender"></zg-column> <zg-column index="species"></zg-column> </zg-colgroup> </zing-grid> </div> </template> </zg-column> </zg-colgroup> </zing-grid> </body> </html>
.zg-body{ background:#fff; } zing-grid[loading] { height: 500px; } zing-grid zing-grid[loading] { height: 91px; } /** Expandable Row Trigger **/ .zg-body .arrow { display:inline-block; transform:rotate(90deg); transform-origin: 0% 0%; cursor:pointer; font-size:1.5rem; position:relative; left:2.5rem; top:0.25rem; } .zg-body .active .arrow { transform:rotate(180deg); left:2.5rem; top:1.5rem; } /** Expandable Row Header **/ .zg-body .row--header { display:flex; align-items:center; } .zg-body .team--info { margin-left:2.5rem; } /** Expandable Row CSS **/ .zg-body zg-cell[type="custom"] { padding:0; } .zg-body .default { border-bottom:1px solid #ebebeb; } .zg-body zg-row:hover { cursor:pointer; background-color:#f5f7fa; transition:background-color 0.25s ease-in; } .zg-body .expandable { background:#f5f5f5; padding:1rem 0; display:none; position:relative; overflow:hidden; } .zg-body .active .expandable { display:block; } /** Set padding **/ /** NOTE: Css looks off here, but it is to fix how it looks on site **/ .zg-body .default--arrow { padding:0.9rem 0; }
function assignDataToNestedGrid(index, cellRef, recordRef) { // assign data to secondary zing-grid let zgRef = cellRef.querySelector('zing-grid'); let data = [recordRef.record]; zgRef.setData(JSON.stringify(data)); } // window:load event for Javascript to run after HTML // because this Javascript is injected into the document head window.addEventListener('load', () => { // Javascript code to execute after DOM content const zgRef = document.querySelector('zing-grid'); zgRef.addEventListener('row:click', bindExpandEvent); function bindExpandEvent(e) { let oDOMRow = e.detail.ZGTarget; oDOMRow.classList.toggle('active'); // refresh the grid to properly size all the columns oDOMRow.querySelector('zing-grid').refresh(); } // open first row zgRef.executeOnLoad(() => { setTimeout(function() { const zgFirstRow = document.querySelector('zg-row[aria-rowindex="2"]'); zgFirstRow.classList.toggle('active'); zgFirstRow.querySelector('zing-grid').refresh(); }, 200); }); });
Interested in this demo? Modify it to your needs in ZingSoft Studio, our testing sandbox. It's free to sign up, and you can come back and edit at any time!