FlexGrid
FlexGrid
Lazy Loading
In the TreeGrid below, collapsed nodes have a single dummy child.
Features
Customer Name
ID
Customer Name
ID
Paul Wang
1
Paul Xie
3
0
The grid currently has 4 rows.
Description
In the TreeGrid below, collapsed nodes have a single dummy child. When a node is expanded, more nodes are loaded on demand. This is a common pattern known as 'lazy-loading', and is done by utilizing the OnClientGroupCollapsedChanged event.
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 | using Microsoft.AspNetCore.Mvc; using Newtonsoft.Json; using System; using System.Collections.Generic; namespace MvcExplorer.Controllers { public partial class FlexGridController : Controller { int ? nodeId; private static readonly Random random = new Random(); // GET: LazyLoading public ActionResult LazyLoading() { List<LazyLoadingItems> items = new List<LazyLoadingItems>(); items.Add(CreateNode()); items.Add(CreateNode()); return View(items); } private LazyLoadingItems CreateNode( bool dummy = false ) { var first = "Al,Bob,Cal,Dan,Ed,Fred,Greg,Hal,Ian,Jack,Karl,Lou,Moe,Nate,Oleg,Paul,Quincy,Rod,Sue,Uwe,Vic,Walt,Xiu,Yuri,Zack" .Split( ',' ); var last = "Adams,Baum,Cole,Dell,Evans,Fell,Green,Hill,Isman,Jones,Krup,Lee,Monk,Nye,Opus,Pitt,Quaid,Riems,Stark,Trell,Unger,Voss,Wang,Xie,Zalm" .Split( ',' ); var name = dummy ? "" : first[random.Next(0, 24)] + ' ' + last[random.Next(0, 24)]; var childrenList = new List<LazyLoadingItems>(); if (!dummy) { childrenList.Add(CreateNode( true )); } if (nodeId == null ) nodeId = 0; var node = new LazyLoadingItems { id = ( int )nodeId, name = name, children = new List<LazyLoadingItems>() }; node.children.AddRange(childrenList); nodeId++; return node; } [HttpGet] public JsonResult GetTreeNodes( int id) { nodeId = id + 1; var newNode = CreateNode(); string str = JsonConvert.SerializeObject(newNode); return Json(str); } } public class LazyLoadingItems { public int id { get ; set ; } public string name { get ; set ; } public List<LazyLoadingItems> children { get ; set ; } } } |
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 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 | @model List< MvcExplorer.Controllers.LazyLoadingItems > @section Styles{ < style > .custom-flex-grid { height: 400px; background-color: white; box-shadow: 4px 4px 10px 0px rgba(50, 50, 50, 0.75); margin-bottom: 12px; max-height: 220px; margin: 6px 0; } .custom-flex-grid .wj-cell { background-color: #fff; border: 1px solid #dad8d8; font-size: 10pt; } .custom-flex-grid .wj-header { background: #eee; } .custom-flex-grid .wj-state-selected { background: #000; color: #fff; } .custom-flex-grid .wj-state-multi-selected { background: #222; color: #fff; } .custom-flex-grid .wj-cell.wj-group { border: 1px solid #dad8d8; } .custom-flex-grid .wj-cell.wj-group:not(.wj-state-selected):not(.wj-state-multi-selected) { background-color: white; } .id-column { font-style: italic; } </ style > } @section Scripts{ <script> var maxId=0; //countains the value of max id of node c1.documentReady( function () { var theGrid = wijmo.Control.getControl( "#grid" ); // start collapsed theGrid.collapseGroupsToLevel(0); updateRowCount(theGrid); }); // update row when items are loaded function updateRowCount(grid) { document.getElementById( 'rowCount' ).textContent = wijmo.Globalize.format(grid.rows.length, 'n0' ); } // load data when collapse node is expanded function groupCollapsedChanged(s, e) { var row = s.rows[e.row], item = row.dataItem; // did we just expand a node with a dummy child? if (!row.isCollapsed && item.children.length == 1 && item.children[0].name == '' ) { // can't lazy load while updating rows if (s.rows.isUpdating) { row.isCollapsed = true ; return ; } // replace the dummy child with actual nodes item.children.length = 0; var cnt = Math.round(Math.random() * 5) + 1; maxId = maxId == 0 ? Math.max.apply(Math, s.collectionView.items.map( function (o) { return o.id; })) : maxId; for ( var i = 0; i < cnt ; i++) { createNode(item, maxId); } s.collectionView._disableServerRead = true ; // refresh the view s.collectionView.refresh(); // collapse the new item's child items for ( var i = row .index + 1; i < s.rows.length; i++) { var childRow = s .rows[i]; if (childRow.level <= row.level) { break ; } childRow.isCollapsed = true ; } // update row count updateRowCount(s); } } function createNode(item, nodeId) { //call action to create new node $.ajax({ async: false , method: 'GET' , url: '@Url.Action("GetTreeNodes", "FlexGrid")' , dataType: "json" , data: {id: nodeId}, contentType: 'application/json; ' , success: function (result) { var data = JSON .parse(result); //push new item item.children.push(data); maxId = data .id; }, error: function (xhr) { alert(xhr.responseText); } }); } </script> } < c1-flex-grid id = "grid" class = "custom-flex-grid" width = "500px" child-items-path = "children" auto-generate-columns = "false" headers-visibility = "Column" selection-mode = "Row" group-collapsed-changed = "groupCollapsedChanged" > < c1-items-source source-collection = "@Model" ></ c1-items-source > < c1-flex-grid-column binding = "name" header = "Customer Name" width = "2*" ></ c1-flex-grid-column > < c1-flex-grid-column binding = "id" header = "ID" width = "1*" align = "center" css-class-all = "id-column" ></ c1-flex-grid-column > </ c1-flex-grid > < p > @Html .Raw(FlexGridRes.TreeGrid_LazyLoading_Text) < b id = "rowCount" ></ b > @Html .Raw(FlexGridRes.TreeGrid_LazyLoading_Text1) </ p > @section Description { @Html .Raw(FlexGridRes.TreeGrid_LazyLoading_Description) } |