明细行

有时,行绑定到包含的信息比包含在常规网格上的信息更多的数据对象。

在这些情况下,您可能希望使用 wijmo.grid.detail 模块中包含的 FlexGridDetailProvider 类。

FlexGridDetailProvider 通过向行标题添加折叠/展开按钮来扩展 FlexGrid,以及可用于提供有关项目的其他详细信息的 createDetailCell 方法。 详细信息显示在展开详细信息时添加到网格中的“详细信息行”中,并在折叠时删除。

import 'bootstrap.css'; import '@grapecity/wijmo.styles/wijmo.css'; import './styles.css'; import { ODataCollectionView } from '@grapecity/wijmo.odata'; import { FlexGrid, HeadersVisibility } from '@grapecity/wijmo.grid'; import { FlexGridDetailProvider } from '@grapecity/wijmo.grid.detail'; document.readyState === 'complete' ? init() : window.onload = init; function init() { // get OData categories and products var url = 'https://services.odata.org/Northwind/Northwind.svc'; var categories = new ODataCollectionView(url, 'Categories', { fields: ['CategoryID', 'CategoryName', 'Description'] }); var products = new ODataCollectionView(url, 'Products'); // shared column definitions var categoryColumns = [ { binding: 'CategoryName', header: 'Category Name', width: '*' }, { binding: 'Description', header: 'Description', width: '2*' } ]; // get products for a given category function getProducts(categoryID) { var arr = []; products.items.forEach(function (product) { if (product.CategoryID == categoryID) { arr.push(product); } }); return arr; } // grid with HTML detail var htmlDetail = new FlexGrid('#htmlDetail', { autoGenerateColumns: false, columns: categoryColumns, itemsSource: categories, isReadOnly: true }); // html detail provider var dpHtml = new FlexGridDetailProvider(htmlDetail, { // use animation when showing details isAnimated: true, // create detail cells for a given row 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 = new FlexGrid('#gridDetail', { autoGenerateColumns: false, columns: categoryColumns, itemsSource: categories, isReadOnly: true }); // grid detail provider var dpGrid = new FlexGridDetailProvider(gridDetail, { // use animation when showing details isAnimated: true, // limit height of detail rows maxHeight: 150, // create detail cells for a given row createDetailCell: function (row) { var cell = document.createElement('div'); var detailGrid = new FlexGrid(cell, { headersVisibility: HeadersVisibility.Column, isReadOnly: true, 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; } }); } <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <title>GrapeCity Wijmo FlexGrid Row Details</title> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <!-- SystemJS --> <script src="node_modules/systemjs/dist/system.src.js"></script> <script src="systemjs.config.js"></script> <script> System.import('./src/app'); </script> </head> <body> <div class="container-fluid"> <h3> HTML in Row Details</h3> <p> This grid shows product categories on each row. Expanding the rows shows an HTML element with information about the products in that category:</p> <div id="htmlDetail"></div> <h3> Grids in Row Details</h3> <p> 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:</p> <div id="gridDetail"></div> </div> </body> </html> .wj-flexgrid { max-height: 350px; } body { margin-bottom: 20pt; } import 'bootstrap.css'; import '@grapecity/wijmo.styles/wijmo.css'; import './styles.css'; // import { Component, enableProdMode, NgModule, ViewChild } from '@angular/core'; import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; import { BrowserModule } from '@angular/platform-browser'; import * as wjcOData from '@grapecity/wijmo.odata'; import * as wjcGrid from '@grapecity/wijmo.grid'; import * as wjcGridDetail from '@grapecity/wijmo.grid.detail'; import { WjGridModule } from '@grapecity/wijmo.angular2.grid'; import { WjGridDetailModule } from '@grapecity/wijmo.angular2.grid.detail'; // @Component({ selector: 'app-component', templateUrl: 'src/app.component.html' }) export class AppComponent { categories: wjcOData.ODataCollectionView; private _products: wjcOData.ODataCollectionView; // DataSvc will be passed by derived classes constructor() { // get OData categories and products let url = 'https://services.odata.org/Northwind/Northwind.svc'; this.categories = new wjcOData.ODataCollectionView(url, 'Categories', { fields: ['CategoryID', 'CategoryName', 'Description'] }) this._products = new wjcOData.ODataCollectionView(url, 'Products'); } @ViewChild('htmlDetail') htmlDetail: wjcGrid.FlexGrid; @ViewChild('gridDetail') gridDetail: wjcGrid.FlexGrid; ngOnInit() { // html detail provider new wjcGridDetail.FlexGridDetailProvider(this.htmlDetail, { // use animation when showing details isAnimated: true, // create detail cells for a given row createDetailCell: (row: wjcGrid.Row) => { // build detail content for the current category let cat = row.dataItem, prods = this._getProducts(cat.CategoryID), 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((product: any) => { html += '<li>' + product.ProductName + '</li>'; }); html += '</ol>'; // create and return detail cell let cell = document.createElement('div'); cell.innerHTML = html; return cell; } }); // grid detail provider new wjcGridDetail.FlexGridDetailProvider(this.gridDetail, { // use animation when showing details isAnimated: true, // limit height of detail rows maxHeight: 150, // create detail cells for a given row createDetailCell: (row: wjcGrid.Row) => { let cell = document.createElement('div') new wjcGrid.FlexGrid(cell, { headersVisibility: wjcGrid.HeadersVisibility.Column, isReadOnly: true, autoGenerateColumns: false, itemsSource: this._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; } }); } private _getProducts(categoryID: string): any[] { let arr: any[] = []; this._products.items.forEach(function(product) { if (product.CategoryID == categoryID) { arr.push(product); } }); return arr; } } // @NgModule({ imports: [WjGridModule, WjGridDetailModule, BrowserModule], declarations: [AppComponent], bootstrap: [AppComponent] }) export class AppModule { } // enableProdMode(); // Bootstrap application with hash style navigation and global services. platformBrowserDynamic().bootstrapModule(AppModule); <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <title>GrapeCity Wijmo FlexGrid Row Details</title> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <!-- Polyfills --> <script src="node_modules/core-js/client/shim.min.js"></script> <script src="node_modules/zone.js/dist/zone.min.js"></script> <!-- SystemJS --> <script src="node_modules/systemjs/dist/system.js"></script> <script src="systemjs.config.js"></script> <script> // workaround to load 'rxjs/operators' from the rxjs bundle System.import('rxjs').then(function (m) { System.set(SystemJS.resolveSync('rxjs/operators'), System.newModule(m.operators)); System.import('./src/app.component'); }); </script> </head> <body> <app-component></app-component> </body> </html> <div class="container-fluid"> <h3>HTML in Row Details</h3> <p> This grid shows product categories on each row. Expanding the rows shows an HTML element with information about the products in that category:</p> <wj-flex-grid #htmlDetail [isReadOnly]="true" [(itemsSource)]="categories"> <wj-flex-grid-column [binding]="'CategoryName'" [header]="'Category Name'" [width]="'*'"></wj-flex-grid-column> <wj-flex-grid-column [binding]="'Description'" [header]="'Description'" [width]="'2*'"></wj-flex-grid-column> </wj-flex-grid> <h3>Grids in Row Details</h3> <p> 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:</p> <wj-flex-grid #gridDetail [isReadOnly]="true" [(itemsSource)]="categories"> <wj-flex-grid-column [binding]="'CategoryName'" [header]="'Category Name'" [width]="'*'"></wj-flex-grid-column> <wj-flex-grid-column [binding]="'Description'" [header]="'Description'" [width]="'2*'"></wj-flex-grid-column> </wj-flex-grid> </div> .wj-flexgrid { max-height: 350px; } body { margin-bottom: 20pt; } <template> <div class="container-fluid"> <h3>HTML in Row Details</h3> <p> This grid shows product categories on each row. Expanding the rows shows an HTML element with information about the products in that category:</p> <wj-flex-grid id="htmlDetail" :initialized="initDetail" :isReadOnly="true" :itemsSource="categories"> <wj-flex-grid-column :binding="'CategoryName'" :header="'Category Name'" :width="'*'"></wj-flex-grid-column> <wj-flex-grid-column :binding="'Description'" :header="'Description'" :width="'2*'"></wj-flex-grid-column> </wj-flex-grid> <h3>Grids in Row Details</h3> <p> 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:</p> <wj-flex-grid id="gridDetail" :initialized="initDetail" :isReadOnly="true" :itemsSource="categories"> <wj-flex-grid-column :binding="'CategoryName'" :header="'Category Name'" :width="'*'"></wj-flex-grid-column> <wj-flex-grid-column :binding="'Description'" :header="'Description'" :width="'2*'"></wj-flex-grid-column> </wj-flex-grid> </div> </template> <script> import "@grapecity/wijmo.styles/wijmo.css"; import 'bootstrap.css'; import Vue from 'vue'; import * as wjcOData from '@grapecity/wijmo.odata'; import * as wjcGrid from '@grapecity/wijmo.grid'; import * as wjcGridDetail from '@grapecity/wijmo.grid.detail'; import '@grapecity/wijmo.vue2.core'; import '@grapecity/wijmo.vue2.grid'; let App = Vue.extend({ name: 'app', data: function(){ let url = 'https://services.odata.org/Northwind/Northwind.svc'; return { categoryColumns: [ { binding: 'CategoryName', header: 'Category Name', width: '*' }, { binding: 'Description', header: 'Description', width: '2*' } ], categories: new wjcOData.ODataCollectionView(url, 'Categories', { fields: ['CategoryID', 'CategoryName', 'Description'] }), products: new wjcOData.ODataCollectionView(url, 'Products'), htmlDetail: null, gridDetail: null } }, methods: { initDetail: function(g){ this[g.hostElement.id] = g; }, getProducts: function(categoryID){ let arr = []; this.products.items.forEach(function(product) { if (product.CategoryID == categoryID) { arr.push(product); } }); return arr; } }, mounted: function(){ new wjcGridDetail.FlexGridDetailProvider(this.htmlDetail, { // use animation when showing details isAnimated: true, // create detail cells for a given row createDetailCell: (row) => { // build detail content for the current category let cat = row.dataItem, prods = this.getProducts(cat.CategoryID), 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((product) => { html += '<li>' + product.ProductName + '</li>'; }); html += '</ol>'; // create and return detail cell let cell = document.createElement('div'); cell.innerHTML = html; return cell; } }); // grid detail provider new wjcGridDetail.FlexGridDetailProvider(this.gridDetail, { // use animation when showing details isAnimated: true, // limit height of detail rows maxHeight: 150, // create detail cells for a given row createDetailCell: (row) => { let cell = document.createElement('div') new wjcGrid.FlexGrid(cell, { headersVisibility: wjcGrid.HeadersVisibility.Column, isReadOnly: true, autoGenerateColumns: false, itemsSource: this.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; } }); } }) new Vue({ render: h => h(App) }).$mount('#app'); </script> <style> .wj-flexgrid { max-height: 350px; } body { margin-bottom: 20pt; } </style> <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <title>AutoComplete</title> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <!-- SystemJS --> <script src="node_modules/systemjs/dist/system.src.js"></script> <script src="systemjs.config.js"></script> <script> System.import('./src/app.vue'); </script> </head> <body> <div id="app"> </div> </body> </html> import "@grapecity/wijmo.styles/wijmo.css"; import "bootstrap.css"; import "./app.css"; // import * as React from 'react'; import * as ReactDOM from 'react-dom'; import * as wjGrid from "@grapecity/wijmo.grid"; import * as wjcGridDetail from "@grapecity/wijmo.grid.detail"; import * as wjcOData from "@grapecity/wijmo.odata"; class App extends React.Component { constructor(props) { super(props); let url = 'https://services.odata.org/Northwind/Northwind.svc'; this.state = { categoryColumns: [ { binding: 'CategoryName', header: 'Category Name', width: '*' }, { binding: 'Description', header: 'Description', width: '2*' } ], categories: new wjcOData.ODataCollectionView(url, 'Categories', { fields: ['CategoryID', 'CategoryName', 'Description'] }), products: new wjcOData.ODataCollectionView(url, 'Products'), htmlDetail: null, gridDetail: null }; } componentDidMount() { var htmlDetail = new wjGrid.FlexGrid('#htmlDetail', { autoGenerateColumns: false, columns: this.state.categoryColumns, itemsSource: this.state.categories, isReadOnly: true }); new wjcGridDetail.FlexGridDetailProvider(htmlDetail, { // use animation when showing details isAnimated: true, // create detail cells for a given row createDetailCell: (row) => { // build detail content for the current category let cat = row.dataItem, prods = this.getProducts(cat.CategoryID), 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((product) => { html += '<li>' + product.ProductName + '</li>'; }); html += '</ol>'; // create and return detail cell let cell = document.createElement('div'); cell.innerHTML = html; return cell; } }); var gridDetail = new wjGrid.FlexGrid('#gridDetail', { autoGenerateColumns: false, columns: this.state.categoryColumns, itemsSource: this.state.categories, isReadOnly: true }); // grid detail provider new wjcGridDetail.FlexGridDetailProvider(gridDetail, { // use animation when showing details isAnimated: true, // limit height of detail rows maxHeight: 150, // create detail cells for a given row createDetailCell: (row) => { let cell = document.createElement('div'); new wjGrid.FlexGrid(cell, { headersVisibility: wjGrid.HeadersVisibility.Column, isReadOnly: true, autoGenerateColumns: false, itemsSource: this.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; } }); } render() { return <div className="container-fluid"> <h3>HTML in Row Details</h3> <p> This grid shows product categories on each row. Expanding the rows shows an HTML element with information about the products in that category:</p> <div id="htmlDetail"></div> <h3>Grids in Row Details</h3> <p> 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:</p> <div id="gridDetail"></div> </div>; } getProducts(categoryID) { let arr = []; this.state.products.items.forEach(function (product) { if (product.CategoryID == categoryID) { arr.push(product); } }); return arr; } } ReactDOM.render(<App />, document.getElementById('app')); <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <title>Grapecity Wijmo OLAP Pivot Chart Overview</title> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <!-- SystemJS --> <script src="node_modules/systemjs/dist/system.src.js"></script> <script src="systemjs.config.js"></script> <script> System.import('./src/app'); </script> </head> <body> <div id="app"></div> </body> </html> .wj-flexgrid { max-height: 350px; } body { margin-bottom: 20pt; }