Row Details
Sometimes rows are bound to data objects that contain more information than what would fit easily on a regular grid.
In these scenarios, you may want to use the FlexGridDetailProvider class that is included with the wijmo.grid.detail module.
FlexGridDetailProvider extends the FlexGrid class by adding collapse/expand buttons to row headers, and a createDetailCell method that can be used to provide additional details about an item. The detail information is shown in a 'detail row' added to the grid when the details are expanded, and removed when they are collapsed.
HTML in Row Details
This grid shows product categories on each row. Expanding the rows shows an HTML element with information about the products in that category.
Grids in Row Details
You can add anything you want to the detail rows, including other grids. This example shows the same categories, but the detail row uses another grid to show the products.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 | // This file locates: "Scripts/Lesson/C1FlexGrid/RowsDetails.js". c1.documentReady(function () { // html detail provider var htmlDetail = wijmo.Control.getControl( '#htmlDetail' ); // html detail provider var dpHtml = c1.getExtender(htmlDetail, 'htmlDetailRow' ); // use animation when showing details dpHtml.isAnimated = true ; // create detail cells for a given row dpHtml.createDetailCell = function (row) { // build detail content for the current category var cat = row.dataItem; var prods = getProducts(cat.CategoryID); var html = 'ID: <b>' + cat.CategoryID + '</b><br/>' ; html += 'Name: <b>' + cat.CategoryName + '</b><br/>' ; html += 'Description: <b>' + cat.Description + '</b><br/>' ; html += 'Products: <b>' + prods.length + ' items</b><br/>' ; html += '<ol>' ; prods.forEach(function (product) { html += '<li>' + product.ProductName + '</li>' ; }); html += '</ol>' ; // create and return detail cell var cell = document.createElement( 'div' ); cell.innerHTML = html; return cell; } // grid with grid detail var gridDetail = wijmo.Control.getControl( '#gridDetail' ); // grid detail provider var dpGrid = c1.getExtender(gridDetail, 'gridDetailRow' ); // use animation when showing details dpGrid.isAnimated = true ; // limit height of detail rows dpGrid.maxHeight = 150; // create detail cells for a given row dpGrid.createDetailCell = function (row) { var cell = document.createElement( 'div' ); var detailGrid = new wijmo.grid.FlexGrid(cell, { headersVisibility: wijmo.grid.HeadersVisibility.Column, autoGenerateColumns: false , itemsSource: getProducts(row.dataItem.CategoryID), columns: [ { header: 'ID' , binding: 'ProductID' }, { header: 'Name' , binding: 'ProductName' }, { header: 'Qty/Unit' , binding: 'QuantityPerUnit' }, { header: 'Unit Price' , binding: 'UnitPrice' }, { header: 'Discontinued' , binding: 'Discontinued' } ] }); return cell; } var categories = [], products = []; var categoriesIsDone = false , productsIsDone = false ; function validate() { if (categoriesIsDone && productsIsDone) { htmlDetail.itemsSource = categories; gridDetail.itemsSource = categories; } } // get products for a given category function getProducts(categoryID) { var arr = []; products.forEach(function (product) { if (product.CategoryID == categoryID) { arr.push(product); } }); return arr; } // get data from OData service function getOdata(url, fill, finish) { wijmo.httpRequest(nwindService + url, { success: function (xhr) { var data = JSON.parse(xhr.responseText); fill(data.value); var nextLink = data[ 'odata.nextLink' ]; if (nextLink == null ) { finish(); } else { getOdata(nextLink + '&$format=json' , fill, finish); } } }); } var categoriesUrl = 'Categories?$format=json&$inlinecount=allpages&$select=CategoryID,CategoryName,Description' ; getOdata(categoriesUrl, function (value) { categories = categories.concat(value); }, function () { categoriesIsDone = true ; validate(); }); var productsUrl = 'Products?$format=json&$inlinecount=allpages' ; getOdata(productsUrl, function (value) { products = products.concat(value); }, function () { productsIsDone = true ; validate(); }); }); |
1 2 3 4 5 6 7 8 9 10 11 12 13 | using System.Web.Mvc; namespace LearnMvcClient.Controllers { public partial class C1FlexGridController : Controller { // GET: RowsDetails public ActionResult RowsDetails() { return View(Models.FlexGridData.GetSales()); } } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 | @model IEnumerable< FlexGridData.Sale > < h1 > @Html .Raw(Resources.C1FlexGrid.RowsDetails_Title) </ h1 > < p > @Html .Raw(Resources.C1FlexGrid.RowsDetails_Text1) </ p > < p > @Html .Raw(Resources.C1FlexGrid.RowsDetails_Text2) </ p > < p > @Html .Raw(Resources.C1FlexGrid.RowsDetails_Text3) </ p > < h3 > @Html .Raw(Resources.C1FlexGrid.RowsDetails_Title1) </ h3 > < p > @Html .Raw(Resources.C1FlexGrid.RowsDetails_Text4) </ p > @ (Html.C1().FlexGrid().Id( "htmlDetail" ).Height(250) .AutoGenerateColumns( false ) .Columns(cs=> { cs.Add().Binding( "CategoryName" ).Header( "Category Name" ).Width( "*" ); cs.Add().Binding( "Description" ).Header( "Description" ).Width( "2*" ); }) .ShowDetailRow(d => d.Id( "htmlDetailRow" )) ) < h3 > @Html .Raw(Resources.C1FlexGrid.RowsDetails_Title2) </ h3 > < p > @Html .Raw(Resources.C1FlexGrid.RowsDetails_Text5) </ p > @ (Html.C1().FlexGrid().Id( "gridDetail" ).Height(250) .AutoGenerateColumns( false ) .Columns(cs=> { cs.Add().Binding( "CategoryName" ).Header( "Category Name" ).Width( "*" ); cs.Add().Binding( "Description" ).Header( "Description" ).Width( "2*" ); }) .ShowDetailRow(d => d.Id( "gridDetailRow" )) ) |