In this post, we will create 3-level Grids hierarchy. Each grid in the nesting relationship will be bound to its own data adapter. Let’s see how to achieve that task in a few steps.
1. Include the CSS files. We will use the Dark Blue theme and we include the jqx.base.css and jqx.darkblue.css files.
<link rel="stylesheet" href="../../jqwidgets/styles/jqx.base.css" type="text/css" /><link rel="stylesheet" href="../../jqwidgets/styles/jqx.darkblue.css" type="text/css" />
2. Include the JavaScript files which we will use for the Grid widget.
<script type="text/javascript" src="scripts/jquery-1.7.2.min.js"></script><script type="text/javascript" src="jqwidgets/jqxcore.js"></script><script type="text/javascript" src="jqwidgets/jqxdata.js"></script> <script type="text/javascript" src="jqwidgets/jqxbuttons.js"></script><script type="text/javascript" src="jqwidgets/jqxscrollbar.js"></script><script type="text/javascript" src="jqwidgets/jqxmenu.js"></script><script type="text/javascript" src="jqwidgets/jqxgrid.js"></script><script type="text/javascript" src="jqwidgets/jqxgrid.selection.js"></script>
3. Create an Array of random data records. We’ll use the Array to populate the Grids.
// prepare the datavar data = new Array();var firstNames =[ "Andrew", "Nancy", "Shelley", "Regina", "Yoshi", "Antoni", "Mayumi", "Ian", "Peter", "Lars", "Petra", "Martin", "Sven", "Elio", "Beate", "Cheryl", "Michael", "Guylene"];var lastNames =[ "Fuller", "Davolio", "Burke", "Murphy", "Nagase", "Saavedra", "Ohno", "Devling", "Wilson", "Peterson", "Winkler", "Bein", "Petersen", "Rossi", "Vileid", "Saylor", "Bjorn", "Nodier"];var productNames =[ "Black Tea", "Green Tea", "Caffe Espresso", "Doubleshot Espresso", "Caffe Latte", "White Chocolate Mocha", "Cramel Latte", "Caffe Americano", "Cappuccino", "Espresso Truffle", "Espresso con Panna", "Peppermint Mocha Twist"];var priceValues =[ "2.25", "1.5", "3.0", "3.3", "4.5", "3.6", "3.8", "2.5", "5.0", "1.75", "3.25", "4.0"];for (var i = 0; i < 10; i++) { var row = {}; var productindex = Math.floor(Math.random() * productNames.length); var price = parseFloat(priceValues[productindex]); var quantity = 1 + Math.round(Math.random() * 10); row["firstname"] = firstNames[Math.floor(Math.random() * firstNames.length)]; row["lastname"] = lastNames[Math.floor(Math.random() * lastNames.length)]; row["productname"] = productNames[productindex]; row["price"] = price; row["quantity"] = quantity; row["total"] = price * quantity; data[i] = row;}var source ={ localdata: data, datatype: "array"};
4. Initialize the root-level Grid. Bind to the Grid’s ‘bindingcomplete’ event and call the ‘setrowdetails’ method for setting the details of each Grid row. The initrowdetails property of the Grid is set to point to a function called ‘initlevel2’. That function will be called when a Grid row is expanded and inside the function we will initialize the sub grids.
// set rows details.$("#jqxgrid").bind('bindingcomplete', function (event) { if (event.target.id == "jqxgrid") { $("#jqxgrid").jqxGrid('beginupdate'); var datainformation = $("#jqxgrid").jqxGrid('getdatainformation'); for (i = 0; i < datainformation.rowscount; i++) { var hidden = i > 0 ? true : false; $("#jqxgrid").jqxGrid('setrowdetails', i, "<div id='grid" + i + "' style='margin: 10px;'></div>", 220, hidden); } $("#jqxgrid").jqxGrid('endupdate'); }});var dataAdapter = new $.jqx.dataAdapter(source);// creage jqxgrid$("#jqxgrid").jqxGrid({ width: 670, height: 365, source: dataAdapter, theme: theme, rowdetails: true, initrowdetails: initlevel2, columns: [ { text: 'First Name', dataField: 'firstname', width: 100 }, { text: 'Last Name', dataField: 'lastname', width: 100 }, { text: 'Product', dataField: 'productname', width: 180 }, { text: 'Quantity', dataField: 'quantity', width: 80, cellsalign: 'right' }, { text: 'Unit Price', dataField: 'price', width: 90, cellsalign: 'right', cellsformat: 'c2' }, { text: 'Total', dataField: 'total', cellsalign: 'right', minwidth: 100, cellsformat: 'c2' } ]});
5. Initialize the Sub Grids. We initialize the sub grids in a very similar way. However, the initrowdetails now points to a function called ‘initlevel3’ which initializes the third hierarchy level.
// create nested grid.var initlevel2 = function (index) { var grid = $($.find('#grid' + index)); grid.bind('bindingcomplete', function (event) { if (event.target.id == "grid" + index) { grid.jqxGrid('beginupdate'); var datainformation = grid.jqxGrid('getdatainformation'); for (var i = 0; i < datainformation.rowscount; i++) { var hidden = true; grid.jqxGrid('setrowdetails', i, "<div id='subgrid" + i + "' style='margin: 10px;'></div>", 220, hidden); } grid.jqxGrid('endupdate'); } }); if (grid != null) { var dataAdapter = new $.jqx.dataAdapter(source); grid.jqxGrid({ rowdetails: true, initrowdetails: initlevel3, source: dataAdapter, theme: theme, width: 600, height: 200, columns: [ { text: 'First Name', dataField: 'firstname', width: 100 }, { text: 'Last Name', dataField: 'lastname', width: 100 }, { text: 'Product', dataField: 'productname', width: 180 }, { text: 'Quantity', dataField: 'quantity', cellsalign: 'right' } ] }); }}
6. The final step is to implement the ‘initlevel3’ function. In general, the function creates a new Grid instance on demand and is called when a parent row is expanded.
var initlevel3 = function (index) { var grid = $($.find('#subgrid' + index)); var dataAdapter = new $.jqx.dataAdapter(source); if (grid != null) { grid.jqxGrid({ source: dataAdapter, theme: theme, width: 530, height: 200, columns: [ { text: 'First Name', dataField: 'firstname', width: 100 }, { text: 'Last Name', dataField: 'lastname', width: 100 }, { text: 'Product', dataField: 'productname', width: 180 }, { text: 'Quantity', dataField: 'quantity', cellsalign: 'right' } ] }); }}
Here’s the resulting Grid:
Very useful example… thanks. Any chance of extending the example to show how rows can be added and deleted in the subgrids…
Very useful example. I have a doubt, How to get all N th level data’s manually?