Each row on the grids below represents a product category. To see the products in each category, expand the rows by clicking the plus sign. Expanded rows show a "detail" row below containing arbitrary content (in this case a nested grid with product information).
The detail rows are implemented using the FlexGridDetailProvider class. The FlexGridDetailProvider class has a createDetailCell function that creates HTML elements to show the details for any row. The content of the detail cells is completely customizable.
In addition to the createDetailCell function, the FlexGridDetailProvider class has other properties that allow you to customize when the detail rows are displayed, their dimensions, etc.
This grid uses the FlexGridDetailProvider class directly. It specifies a createDetailCell function that creates child grids to show the products in the category represented by the main row.
The code looks like this:
// create FlexGridDetailProvider for "flex" control
var dp = new wijmo.grid.detail.FlexGridDetailProvider(flex);
dp.maxHeight = 250;
// create and host detail cells
dp.createDetailCell = (row) => {
var cell = document.createElement('div');
var detailGrid = new wijmo.grid.FlexGrid(cell);
detailGrid.itemsSource = this.getProducts(row.dataItem.CategoryID);
detailGrid.headersVisibility = wijmo.grid.HeadersVisibility.Column;
return cell;
}
// remove details from items with odd CategoryID
dp.rowHasDetail = function (row) {
return row.dataItem.CategoryID % 2 == 0;
}
This grid uses the wjFlexGridDetail directive. The directive is defined on a template with a child FlexGrid that shows the products in the category represented by the main row.
The markup looks like this:
<wj-flex-grid [allowDragging]="'Both'"
[itemsSource]="categories">
<wj-flex-grid-column [header]="'Name'" [binding]="'CategoryName'"></wj-flex-grid-column>
<wj-flex-grid-column [header]="'Description'" [binding]="'Description'" [width]="'*'"></wj-flex-grid-column>
<template wjFlexGridDetail [maxHeight]="250" [detailVisibilityMode]="detailMode" let-item="item">
<wj-flex-grid [itemsSource]="getProducts(item.CategoryID)"
[headersVisibility]="'Column'">
<wj-flex-grid-column [header]="'ID'" [binding]="'ProductID'"></wj-flex-grid-column>
<wj-flex-grid-column [header]="'Name'" [binding]="'ProductName'"></wj-flex-grid-column>
<wj-flex-grid-column [header]="'Qty/Unit'" [binding]="'QuantityPerUnit'"></wj-flex-grid-column>
<wj-flex-grid-column [header]="'Unit Price'" [binding]="'UnitPrice'"></wj-flex-grid-column>
<wj-flex-grid-column [header]="'Discontinued'" [binding]="'Discontinued'"></wj-flex-grid-column>
</wj-flex-grid>
</template>
</wj-flex-grid>
Select the value for the detailVisibilityMode property to determine when the row details are visible.
The grid below uses the wjFlexGridDetail directive and specifies a template defined as HTML content, including a list created with an ngFor directive.
The markup looks like this:
<wj-flex-grid [itemsSource]="categories">
<wj-flex-grid-column [header]="'Name'" [binding]="'CategoryName'"></wj-flex-grid-column>
<wj-flex-grid-column [header]="'Description'" [binding]="'Description'" [width]="'*'"></wj-flex-grid-column>
<template wjFlexGridDetail [detailVisibilityMode]="'ExpandSingle'" #item="item">
ID: <b>{{item.CategoryID}}</b><br />
Name: <b>{{item.CategoryName}}</b><br />
Description: <b>{{item.Description}}</b><br />
<ol>
<li *ngFor="let p of getProducts(item.CategoryID).items">{{p.ProductName}}</li>
</ol>
</template>
</wj-flex-grid>
The wj-flex-grid-detail directive has a "control" attribute that you can use to access the methods in its FlexGridDetailProvider class. In this example, we use these methods in the markup to provide custom icons for expanding and collapsing the detail rows.
The nice thing about this approach is that it gives you total control over the user experience, including the appearance and behavior of the elements used to show and hide the detail rows.
The markup looks like this:
<wj-flex-grid [itemsSource]="categories"
[headersVisibility]="'Column'"
[selectionMode]="'Row'">
<template wjFlexGridDetail #dp="wjFlexGridDetail" [detailVisibilityMode]="'Code'" let-item="item">
<div style="padding:12px;background-color:#cee6f7;color:#000">
ID: <b>{{item.CategoryID}}</b><br />
Name: <b>{{item.CategoryName}}</b><br />
Description: <b>{{item.Description}}</b><br />
<button class="btn btn-default" (click)="dp.hideDetail(row)">Hide Detail</button>
</div>
</template>
<wj-flex-grid-column [header]="'Name'" [binding]="'CategoryName'" [isReadOnly]="true" [width]="200">
<template wjFlexGridCellTemplate [cellType]="'Cell'" let-row="row" let-item="item">
<span [ngStyle]="{display: dp?.isDetailAvailable(row) ? '' : 'none'}">
<img [ngStyle]="{display: dp.isDetailVisible(row) ? '' : 'none'}" (click)="dp.hideDetail(row)" src="resources/hide.png" />
<img [ngStyle]="{display: !dp?.isDetailVisible(row) ? '' : 'none'}" (click)="dp.showDetail(row, true)" src="resources/show.png" />
</span>
{{item.CategoryName}} -{{dp.isDetailAvailable(row)}}
</template>
</wj-flex-grid-column>
<wj-flex-grid-column [header]="'Description'" [binding]="'Description'" [width]="'2*'"></wj-flex-grid-column>
</wj-flex-grid>
{{item.CategoryName}} - {{dp.isDetailAvailable(row)}}