グリッド:詳細行

通常のグリッドよりも多くの情報を含むデータオブジェクトが、行に連結されることがあります。これらのシナリオでは、wijmo.grid.detailモジュールに含まれているFlexGridDetailProviderクラスを使用することができます。FlexGridDetailProviderは、FlexGridを拡張して、行ヘッダーに折りたたみ/展開ボタンを追加したり、createDetailCellメソッドを使用して項目に関する詳細情報を提供することができます。詳細情報は「詳細行」に表示され、詳細行は展開されたときにグリッドに追加され、折りたたまれたときに削除されます。

import 'bootstrap.css'; import '@grapecity/wijmo.styles/wijmo.css'; import './styles.css'; import * as wjOdata from '@grapecity/wijmo.odata'; import * as wjGrid from '@grapecity/wijmo.grid'; import * as wjGridDetail 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 wjOdata.ODataCollectionView(url, 'Categories', { fields: ['CategoryID', 'CategoryName', 'Description'] }); var products = new wjOdata.ODataCollectionView(url, 'Products'); // // shared column definitions var categoryColumns = [ { binding: 'CategoryName', header: '分類名', width: '*' }, { binding: 'Description', header: '説明', 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 wjGrid.FlexGrid('#htmlDetail', { autoGenerateColumns: false, columns: categoryColumns, itemsSource: categories, isReadOnly: true }); // // html detail provider var dpHtml = new wjGridDetail.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 += '分類名: <b>' + cat.CategoryName + '</b><br/>'; html += '説明: <b>' + cat.Description + '</b><br/>'; html += '商品: <b>合計' + prods.length + '個</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 wjGrid.FlexGrid('#gridDetail', { autoGenerateColumns: false, columns: categoryColumns, itemsSource: categories, isReadOnly: true }); // // grid detail provider var dpGrid = new wjGridDetail.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 wjGrid.FlexGrid(cell, { headersVisibility: wjGrid.HeadersVisibility.Column, isReadOnly: true, autoGenerateColumns: false, itemsSource: getProducts(row.dataItem.CategoryID), columns: [ { header: 'ID', binding: 'ProductID', width: 80 }, { header: '商品名', binding: 'ProductName', width: '*' }, { header: '梱包単位', binding: 'QuantityPerUnit', width: '*' }, { header: '単価', binding: 'UnitPrice', width: 80 }, { header: '生産中止', 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 Nested Grids</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要素を表示</h3> <p> このグリッドは、各行の商品カテゴリを示します。行を展開すると、そのカテゴリの商品に関する情報が表示されます。</p> <div id="htmlDetail"></div> <h3> グリッドを表示</h3> <p> 他のグリッドを含め、詳細行に任意のものを追加できます。この例は同じカテゴリを示していますが、詳細行は別のグリッドを使って商品を表示します。</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 * as wjOdata from '@grapecity/wijmo.odata'; import * as wjGrid from '@grapecity/wijmo.grid'; import * as wjGridDetail from '@grapecity/wijmo.grid.detail'; import { Component, enableProdMode, NgModule, ChangeDetectionStrategy } from '@angular/core'; import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; import { BrowserModule } from '@angular/platform-browser'; import { WjGridModule } from '@grapecity/wijmo.angular2.grid'; import { WjGridDetailModule } from '@grapecity/wijmo.angular2.grid.detail'; // const url = 'https://services.odata.org/Northwind/Northwind.svc'; // @Component({ selector: 'app-component', templateUrl: 'src/app.component.html' }) export class AppComponent { categories: wjOdata.ODataCollectionView; products: wjOdata.ODataCollectionView; catToProductMap: Map<string, any> = new Map(); // DataSvc will be passed by derived classes constructor() { this.categories = this._getCategories(); this.products = this._getProducts(); } getProducts(categoryID: string) { let categoryProducts = this.catToProductMap.get(categoryID); if (!categoryProducts) { categoryProducts = this.products.items.filter( (product) => product.CategoryID === categoryID); this.catToProductMap.set(categoryID, categoryProducts); } return categoryProducts; } private _getCategories() { return new wjOdata.ODataCollectionView(url, 'Categories', { fields: ['CategoryID', 'CategoryName', 'Description'] }); } private _getProducts() { return new wjOdata.ODataCollectionView(url, 'Products'); } } // @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 Nested Grids</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要素を表示</h3> <p> このグリッドは、各行の商品カテゴリを示します。行を展開すると、そのカテゴリの商品に関する情報が表示されます。</p> <wj-flex-grid [itemsSource]="categories" [isReadOnly]="true"> <wj-flex-grid-column [header]="'分類名'" [binding]="'CategoryName'"></wj-flex-grid-column> <wj-flex-grid-column [header]="'説明'" [binding]="'Description'" [width]="'*'"></wj-flex-grid-column> <ng-template wjFlexGridDetail [isAnimated]=true let-item="item"> ID: <b>{{item.CategoryID}}</b><br /> 分類名: <b>{{item.CategoryName}}</b><br /> 説明: <b>{{item.Description}}</b><br /> 商品: <b>{{getProducts(item.CategoryID).length}}個</b><br /> <ol> <li *ngFor="let p of getProducts(item.CategoryID)">{{p.ProductName}}</li> </ol> </ng-template> </wj-flex-grid> <h3> グリッドを表示</h3> <p> 他のグリッドを含め、詳細行に任意のものを追加できます。この例は同じカテゴリを示していますが、詳細行は別のグリッドを使って商品を表示します。</p> <wj-flex-grid #gridDetail [autoGenerateColumns]=false [itemsSource]="categories" [isReadOnly]=true> <wj-flex-grid-column [header]="'分類名'" [binding]="'CategoryName'" [width]="'*'"></wj-flex-grid-column> <wj-flex-grid-column [header]="'説明'" [binding]="'Description'" [width]="'2*'"></wj-flex-grid-column> <ng-template wjFlexGridDetail [maxHeight]="250" let-item="item"> <wj-flex-grid [itemsSource]="getProducts(item.CategoryID)" [isReadOnly]="true" [headersVisibility]="'Column'"> <wj-flex-grid-column [header]="'ID'" [binding]="'ProductID'"></wj-flex-grid-column> <wj-flex-grid-column [header]="'商品名'" [binding]="'ProductName'"></wj-flex-grid-column> <wj-flex-grid-column [header]="'梱包単位'" [binding]="'QuantityPerUnit'"></wj-flex-grid-column> <wj-flex-grid-column [header]="'単価'" [binding]="'UnitPrice'"></wj-flex-grid-column> <wj-flex-grid-column [header]="'生産中止'" [binding]="'Discontinued'"></wj-flex-grid-column> </wj-flex-grid> </ng-template> </wj-flex-grid> </div> .wj-flexgrid { max-height: 350px; } body { margin-bottom: 20pt; } 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 wjOdata from '@grapecity/wijmo.odata'; import * as wjGrid from '@grapecity/wijmo.grid'; import * as wjGridDetail from '@grapecity/wijmo.grid.detail'; import "@grapecity/wijmo.grid"; import "@grapecity/wijmo.grid.detail"; class App extends React.Component { constructor(props) { super(props); this.categoryColumns = []; var url = 'https://services.odata.org/Northwind/Northwind.svc'; this.state = { categories: new wjOdata.ODataCollectionView(url, 'Categories', { fields: ['CategoryID', 'CategoryName', 'Description'] }), products: new wjOdata.ODataCollectionView(url, 'Products') }; this.categoryColumns = [ { binding: 'CategoryName', header: '分類名', width: '*' }, { binding: 'Description', header: '説明', width: '2*' } ]; } render() { return <div className="container-fluid"> <h3> HTML要素を表示</h3> <p> このグリッドは、各行の商品カテゴリを示します。行を展開すると、そのカテゴリの商品に関する情報が表示されます。</p> <div id="htmlDetail"></div> <h3> グリッドを表示</h3> <p> 他のグリッドを含め、詳細行に任意のものを追加できます。この例は同じカテゴリを示していますが、詳細行は別のグリッドを使って商品を表示します。</p> <div id="gridDetail"></div> </div>; } componentDidMount() { var htmlDetail = new wjGrid.FlexGrid('#htmlDetail', { autoGenerateColumns: false, columns: this.categoryColumns, itemsSource: this.state.categories, isReadOnly: true }); new wjGridDetail.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 var cat = row.dataItem; var prods = this.getProducts(cat.CategoryID); var html = 'ID: <b>' + cat.CategoryID + '</b><br/>'; html += '分類名: <b>' + cat.CategoryName + '</b><br/>'; html += '説明: <b>' + cat.Description + '</b><br/>'; html += '商品: <b>合計' + prods.length + '個</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; } }); var gridDetail = new wjGrid.FlexGrid('#gridDetail', { autoGenerateColumns: false, columns: this.categoryColumns, itemsSource: this.state.categories, isReadOnly: true }); // grid detail provider new wjGridDetail.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) => { var cell = document.createElement('div'); var detailGrid = new wjGrid.FlexGrid(cell, { headersVisibility: wjGrid.HeadersVisibility.Column, isReadOnly: true, autoGenerateColumns: false, itemsSource: this.getProducts(row.dataItem.CategoryID), columns: [ { header: 'ID', binding: 'ProductID', width: 80 }, { header: '商品名', binding: 'ProductName', width: '*' }, { header: '梱包単位', binding: 'QuantityPerUnit', width: '*' }, { header: '単価', binding: 'UnitPrice', width: 80 }, { header: '生産中止', binding: 'Discontinued' } ] }); return cell; } }); } getProducts(categoryID) { var 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 FlexGrid Nested Grids</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; } <script> import "@grapecity/wijmo.styles/wijmo.css"; import "bootstrap.css"; import Vue from "vue"; import * as wjOdata from '@grapecity/wijmo.odata'; import * as wjGrid from '@grapecity/wijmo.grid'; import * as wjGridDetail from '@grapecity/wijmo.grid.detail'; import "@grapecity/wijmo.vue2.grid"; import "@grapecity/wijmo.vue2.grid.detail"; let App = Vue.extend({ name: "app", template: `<div class="container-fluid"> <h3> HTML要素を表示</h3> <p> このグリッドは、各行の商品カテゴリを示します。行を展開すると、そのカテゴリの商品に関する情報が表示されます。</p> <wj-flex-grid :itemsSource="categories" :isReadOnly=true> <wj-flex-grid-column header="分類名" binding="CategoryName"></wj-flex-grid-column> <wj-flex-grid-column header="説明" binding="Description" width="*"></wj-flex-grid-column> <wj-flex-grid-detail :initialized="initializeCategory" :isAnimated=true> <template slot-scope="props"> ID: <b>{{props.item.CategoryID}}</b><br /> 分類名: <b>{{props.item.CategoryName}}</b><br /> 説明: <b>{{props.item.Description}}</b><br /> 商品: <b>{{getProducts(props.item.CategoryID).length}}個</b><br /> <ol> <li v-for="p in getProducts(props.item.CategoryID)" v-bind:key="p">{{p.ProductName}}</li> </ol> </template> </wj-flex-grid-detail> </wj-flex-grid> <h3> グリッドを表示</h3> <p> 他のグリッドを含め、詳細行に任意のものを追加できます。この例は同じカテゴリを示していますが、詳細行は別のグリッドを使って商品を表示します。</p> <wj-flex-grid :autoGenerateColumns=false :itemsSource="categories" :isReadOnly=true> <wj-flex-grid-column header="分類名" binding="CategoryName" width="*"></wj-flex-grid-column> <wj-flex-grid-column header="説明" binding="Description" width="2*"></wj-flex-grid-column> <wj-flex-grid-detail :maxHeight=250> <template slot-scope="props"> <wj-flex-grid :itemsSource="getProducts(props.item.CategoryID)" :isReadOnly="true" headersVisibility="Column"> <wj-flex-grid-column header="ID" binding="ProductID"></wj-flex-grid-column> <wj-flex-grid-column header="商品名" binding="ProductName"></wj-flex-grid-column> <wj-flex-grid-column header="梱包単位" binding="QuantityPerUnit"></wj-flex-grid-column> <wj-flex-grid-column header="単価" binding="UnitPrice"></wj-flex-grid-column> <wj-flex-grid-column header="生産中止" binding="Discontinued"></wj-flex-grid-column> </wj-flex-grid> </template> </wj-flex-grid-detail> </wj-flex-grid> </div>`, data: function() { return { categories : null, products : null }; }, methods: { initializeCategory: function(ctl){ this.wjFlexGridDetail = ctl; }, getProducts(categoryID) { var arr = []; this.products.items.forEach(function (product) { if (product.CategoryID == categoryID) { arr.push(product); } }); return arr; } }, mounted: function() { var url = 'https://services.odata.org/Northwind/Northwind.svc'; this.categories = new wjOdata.ODataCollectionView(url, 'Categories', { fields: ['CategoryID', 'CategoryName', 'Description'] }); this.products = new wjOdata.ODataCollectionView(url, 'Products'); } }); 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>GrapeCity Wijmo FlexGrid Nested Grids</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>