Grouping and Drill-Down
This example shows how you can leverage the grouping features in the CollectionView class to create drill-down charts.
Click on the bars to drill-down into any group. The chart will be updated to show the new data, and the chart's header will show breadcrumbs so you can navigate back up the group hierarchy:
Sales
- C1FlexChart/GroupingDrillDown.js
- C1FlexChart/GroupingDrillDown.css
- GroupingDrillDownController.cs
- GroupingDrillDown.cshtml
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 132 133 134 135 136 | // This file locates: "Scripts/Lesson/C1FlexChart/GroupingDrillDown.js". c1.documentReady(function () { var theChart = wijmo.Control.getControl( '#theChart' ); // create a CollectionView containing data grouped by // country, product, color, and type var view = new wijmo.collections.CollectionView(getData(), { groupDescriptions: 'country,product,color,type' .split( ',' ) }); theChart.itemsSource = getGroupData(view); // show first-level grouping theChart.selectionChanged.addHandler(function (s, e) { if (s.selection) { var point = s.selection.collectionView.currentItem; if (point && point.group && !point.group.isBottomLevel) { showGroup(point.group); } } }) // show a group on the chart function showGroup(group) { // update titles updateChartHeader(group); var level = 'level' in group ? group.level + 1 : 0; theChart.axisX.title = wijmo.toHeaderCase(view.groupDescriptions[level].propertyName); // update the series color (use a different one for each level) var palette = theChart.palette || wijmo.chart.Palettes.standard; theChart.series[0].style = { fill: palette[level], stroke: palette[level] }; // update data theChart.itemsSource = getGroupData(group); theChart.selection = null ; } // update the chart header element var header = document.getElementById( 'header' ); function updateChartHeader(group) { var item = group.items[0], path = '' , headers = []; for (var i = 0; i <= group.level; i++) { var prop = view.groupDescriptions[i].propertyName, hdr = wijmo.format( '<a href="#{path}">{prop}</a>: {value}' , { path: path, prop: wijmo.toHeaderCase(prop), value: item[prop] }); headers.push(hdr); path += '/' + item[prop]; } header.innerHTML = headers.length > 0 ? 'Sales for ' + headers.join( ', ' ) : 'Sales' ; } // handle clicks on chart's header element to navigate back up header.addEventListener( 'click' , function (e) { if (e.target instanceof HTMLAnchorElement) { e.preventDefault(); // get the link path var path = e.target.href; path = path.substr(path.lastIndexOf( '#' ) + 1); path = path.split( '/' ); // find the group that matches the path var src = view; for (var i = 1; i < path.length; i++) { for (var j = 0; j < src.groups.length; j++) { var group = src.groups[j]; if (group.name == path[i]) { src = group; break ; } } } // show the selected group showGroup(src); } }); // get the group data for a selected point function getGroupData(group) { // get items for this group, aggregate by sales var arr = []; group.groups.forEach(function (g) { arr.push({ name: g.name, sales: g.getAggregate( 'Sum' , 'sales' ), group: g }); }); // return a new collection view sorted by sales return new wijmo.collections.CollectionView(arr, { sortDescriptions: [ new wijmo.collections.SortDescription( 'sales' , false ) ] }); } // create some random data function getData() { var countries = 'US,Canada,Germany,UK,France,Italy,Japan,Korea,China' .split( ',' ); var products = 'Piano,Violin,Flute,Guitar,Cello' .split( ',' ); var colors = 'Red,Green,Blue,Brown,White,Black' .split( ',' ); var types = 'Hobbyist,Average,Professional,Collector' .split( ',' ); var data = []; for (var i = 0; i < 1000; i++) { data.push({ id: i, country: randomItem(countries), product: randomItem(products), color: randomItem(colors), type: randomItem(types), sales: Math.random() * 10000, expenses: Math.random() * 5000 }); } return data; } function randomItem(items) { return items[Math.floor(Math.random() * items.length)]; } }); |
1 2 3 4 5 6 7 8 9 10 | // This file locates: "Content/css/Lesson/C1FlexChart/GroupingDrillDown.css". .chart-host { border: 1px solid #e4e4e4; } .chart-host h4 { text-align: center; } .chart-host a { cursor: pointer; } |
1 2 3 4 5 6 7 8 9 10 11 12 13 | using System.Web.Mvc; namespace LearnMvcClient.Controllers { public partial class C1FlexChartController : Controller { // GET: GroupingDrillDown public ActionResult GroupingDrillDown() { return View(); } } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | < h1 > @Html .Raw(Resources.C1FlexChart.GroupingDrillDown_Title) </ h1 > < p > @Html .Raw(Resources.C1FlexChart.GroupingDrillDown_Text1) </ p > < p > @Html .Raw(Resources.C1FlexChart.GroupingDrillDown_Text2) </ p > < div class = "chart-host" > < h4 id = "header" > @Html .Raw(Resources.C1FlexChart.GroupingDrillDown_Text3)</ h4 > @ (Html.C1().FlexChart().Id( "theChart" ) .BindingX( "name" ) .Series(sb=>sb.Add().Binding( "sales" ).Name( "Sales" )) .AxisX(x=>x.Title( "Country" )) .AxisY(y=>y.Title( "Sales (US$ thousands)" ).Format( "n0," )) .Legend(C1.Web.Mvc.Chart.Position.None) .Tooltip(t=>t.Content( "" )) .SelectionMode(C1.Web.Mvc.Chart.SelectionMode.Point) ) </ div > |