OData and Virtual Data

The ODataCollectionView class provides a simple way to connect controls to OData sources. When you create an ODataCollectionView, it starts loading the data in the source. The ODataVirtualCollectionView extends ODataCollectionView to provide on-demand loading of data. It does not load the data from the server automatically. Instead, it relies on the setWindow method to load data fragments (windows) on demand. The grids below show how both classes work. Notice how the grid on the left shows the data being loaded gradually. The grid on the right shows the full record count immediately, but the data will not be loaded until you scroll down.

import 'bootstrap.css'; import '@grapecity/wijmo.styles/wijmo.css'; import './styles.css'; import { format } from '@grapecity/wijmo'; import { ODataCollectionView, ODataVirtualCollectionView } from '@grapecity/wijmo.odata'; import { FlexGrid, CellType } from '@grapecity/wijmo.grid'; document.readyState === 'complete' ? init() : window.onload = init; function init() { // get order details into an ODataCollectionView var url = 'https://services.odata.org/Northwind/Northwind.svc'; var table = 'Order_Details_Extendeds'; var orderDetails = new ODataCollectionView(url, table); // show the data on a grid var itemCountElement = document.getElementById('itemCount'); var theGrid = new FlexGrid('#theGrid', { itemsSource: orderDetails, isReadOnly: true, formatItem: function (s, e) { if (e.panel.cellType == CellType.RowHeader) { e.cell.textContent = e.row + 1; } }, loadedRows: function (sender, e) { var el = document.getElementById('itemCount'); el.innerHTML = format('{length:n0} items', sender.rows); } }); // get order details into a ODataVirtualCollectionView var virtualDetails = new ODataVirtualCollectionView(url, table, { loaded: function (sender, e) { var el = document.getElementById('totalItemCount'); el.innerHTML = format('{totalItemCount:n0} items', sender); } }); // show the data on a grid var theVirtualGrid = new FlexGrid('#theVirtualGrid', { itemsSource: virtualDetails, isReadOnly: true, formatItem: function (s, e) { if (e.panel.cellType == CellType.RowHeader) { e.cell.textContent = e.row + 1; } }, scrollPositionChanged: function () { var rng = theVirtualGrid.viewRange; virtualDetails.setWindow(rng.row, rng.row2); } }); } <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <title>GrapeCity Wijmo FlexGrid OData and Virtual OData Binding</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"> <div class="row"> <div class="col-sm-6"> <h4>ODataCollectionView</h4> <p id="itemCount"></p> <div id="theGrid"></div> </div> <div class="col-sm-6"> <h4>ODataVirtualCollectionView</h4> <p id="totalItemCount"></p> <div id="theVirtualGrid"></div> </div> </div> </div> </body> </html> .wj-flexgrid { height: 300px; } .wj-flexgrid .wj-rowheaders .wj-cell { font-size: 80%; padding-top: .5em; } body { margin-bottom: 20pt; } import 'bootstrap.css'; import '@grapecity/wijmo.styles/wijmo.css'; import './styles.css'; // import { Component, enableProdMode, NgModule } from '@angular/core'; import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; import { BrowserModule } from '@angular/platform-browser'; import * as wjcCore from '@grapecity/wijmo'; import * as wjcGrid from '@grapecity/wijmo.grid'; import * as wjcOData from '@grapecity/wijmo.odata'; import { WjGridModule } from '@grapecity/wijmo.angular2.grid'; // @Component({ selector: 'app-component', templateUrl: 'src/app.component.html' }) export class AppComponent { orderDetails: wjcOData.ODataCollectionView; virtualOrderDetails: wjcOData.ODataVirtualCollectionView; itemCount: string; totalItemCount: string; // DataSvc will be passed by derived classes constructor() { // get order details into an ODataCollectionView let url = 'https://services.odata.org/Northwind/Northwind.svc', table = 'Order_Details_Extendeds'; this.orderDetails = new wjcOData.ODataCollectionView(url, table); this.virtualOrderDetails = new wjcOData.ODataVirtualCollectionView(url, table, { loaded: (sender: any, e: any) => { this.totalItemCount = wjcCore.format('{totalItemCount:n0} items', sender); } }); } gridInitialized(flexgrid: wjcGrid.FlexGrid) { flexgrid.formatItem.addHandler((s: wjcGrid.FlexGrid, e: wjcGrid.FormatItemEventArgs) => { // show row indices in row headers if (e.panel.cellType == wjcGrid.CellType.RowHeader) { e.cell.textContent = (e.row + 1).toString(); } }); flexgrid.loadedRows.addHandler((sender: wjcGrid.FlexGrid, e: wjcCore.EventArgs) => { this.itemCount = wjcCore.format('{length:n0} items', sender.rows); }); } virtualGridInitialized(flexgrid: wjcGrid.FlexGrid) { flexgrid.formatItem.addHandler((s: wjcGrid.FlexGrid, e: wjcGrid.FormatItemEventArgs) => { // show row indices in row headers if (e.panel.cellType == wjcGrid.CellType.RowHeader) { e.cell.textContent = (e.row + 1).toString(); } }); flexgrid.scrollPositionChanged.addHandler(() => { let rng = flexgrid.viewRange; this.virtualOrderDetails.setWindow(rng.row, rng.row2); }); } } // @NgModule({ imports: [WjGridModule, 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 OData and Virtual OData Binding</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"> <div class="col-sm-6"> <h4>ODataCollectionView</h4> <p>{{itemCount}}</p> <wj-flex-grid #grid [(itemsSource)]="orderDetails" [isReadOnly]="true" (initialized)="gridInitialized(grid)"> </wj-flex-grid> </div> <div class="col-sm-6"> <h4>ODataVirtualCollectionView</h4> <p>{{totalItemCount}}</p> <wj-flex-grid #virtualGrid [(itemsSource)]="virtualOrderDetails" [isReadOnly]="true" (initialized)="virtualGridInitialized(virtualGrid)"> </wj-flex-grid> </div> </div> .wj-flexgrid { height: 300px; } .wj-flexgrid .wj-rowheaders .wj-cell { font-size: 80%; padding-top: .5em; } body { margin-bottom: 20pt; } <template> <div class="container-fluid"> <div class="col-sm-6"> <h4>ODataCollectionView</h4> <p>{{itemCount}}</p> <wj-flex-grid :itemsSource="orderDetails" :isReadOnly="true" :initialized="gridInitialized" ></wj-flex-grid> </div> <div class="col-sm-6"> <h4>ODataVirtualCollectionView</h4> <p>{{totalItemCount}}</p> <wj-flex-grid :itemsSource="virtualOrderDetails" :isReadOnly="true" :initialized="virtualGridInitialized" ></wj-flex-grid> </div> </div> </template> <script> import "@grapecity/wijmo.styles/wijmo.css"; import "bootstrap.css"; import Vue from "vue"; import "@grapecity/wijmo.vue2.grid"; import * as wjcGrid from "@grapecity/wijmo.grid"; import * as wjcOData from "@grapecity/wijmo.odata"; import * as wjcCore from "@grapecity/wijmo"; let App = Vue.extend({ name: "app", data: function() { return { table: "Order_Details_Extendeds", orderDetails: new wjcOData.ODataCollectionView( "https://services.odata.org/Northwind/Northwind.svc", "Order_Details_Extendeds" ), virtualOrderDetails: new wjcOData.ODataVirtualCollectionView( "https://services.odata.org/Northwind/Northwind.svc", "Order_Details_Extendeds", { loaded: (sender, e) => { this.totalItemCount = wjcCore.format( "{totalItemCount:n0} items", sender ); } } ), itemCount: "", totalItemCount: "" }; }, methods: { gridInitialized: function(flexgrid) { this.flexgrid = flexgrid; flexgrid.formatItem.addHandler((s, e) => { // show row indices in row headers if (e.panel.cellType == wjcGrid.CellType.RowHeader) { e.cell.textContent = (e.row + 1).toString(); } }); flexgrid.loadedRows.addHandler((sender, e) => { this.itemCount = wjcCore.format( "{length:n0} items", sender.rows ); }); }, virtualGridInitialized: function(flexgrid) { this.flexgrid = flexgrid; flexgrid.formatItem.addHandler((s, e) => { // show row indices in row headers if (e.panel.cellType == wjcGrid.CellType.RowHeader) { e.cell.textContent = (e.row + 1).toString(); } }); flexgrid.scrollPositionChanged.addHandler(() => { let rng = flexgrid.viewRange; this.virtualOrderDetails.setWindow(rng.row, rng.row2); }); } } }); new Vue({ render: h => h(App) }).$mount("#app"); </script> <style> .wj-flexgrid { height: 350px; } .wj-cell { border-color: #e0e0e0; } .wj-cell.wj-has-notes:after { position: absolute; content: ""; width: 0; right: 0; top: -10px; border: 10px solid transparent; border-right: 10px solid red; opacity: 0.5; } .wj-cell.wj-has-notes:hover:after { opacity: 1; } body { margin-bottom: 24pt; } </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 'bootstrap.css'; import '@grapecity/wijmo.styles/wijmo.css'; import './app.css'; // import * as React from 'react'; import * as ReactDOM from 'react-dom'; import * as wjcCore from "@grapecity/wijmo"; import * as wjcGrid from "@grapecity/wijmo.grid"; import * as wjcOData from "@grapecity/wijmo.odata"; import * as wjGrid from '@grapecity/wijmo.react.grid'; class App extends React.Component { constructor(props) { super(props); this.state = { orderDetails: new wjcOData.ODataCollectionView("https://services.odata.org/Northwind/Northwind.svc", "Order_Details_Extendeds"), virtualOrderDetails: new wjcOData.ODataVirtualCollectionView("https://services.odata.org/Northwind/Northwind.svc", "Order_Details_Extendeds", { loaded: (sender, e) => { this.setState({ totalItemCount: wjcCore.format("{totalItemCount:n0} items", sender) }); } }), itemCount: "", totalItemCount: "" }; } render() { return <div className="container-fluid"> <div className="col-sm-6"> <h4>ODataCollectionView</h4> <p>{this.state.itemCount}</p> <wjGrid.FlexGrid itemsSource={this.state.orderDetails} isReadOnly={true} initialized={this.gridInitialized.bind(this)}> </wjGrid.FlexGrid> </div> <div className="col-sm-6"> <h4>ODataVirtualCollectionView</h4> <p>{this.state.totalItemCount}</p> <wjGrid.FlexGrid itemsSource={this.state.virtualOrderDetails} isReadOnly={true} initialized={this.virtualGridInitialized.bind(this)}> </wjGrid.FlexGrid> </div> </div>; } gridInitialized(flexgrid) { flexgrid.formatItem.addHandler((s, e) => { // show row indices in row headers if (e.panel.cellType == wjcGrid.CellType.RowHeader) { e.cell.textContent = (e.row + 1).toString(); } }); flexgrid.loadedRows.addHandler((sender, e) => { this.setState({ itemCount: wjcCore.format("{length:n0} items", sender.rows) }); }); } virtualGridInitialized(flexgrid) { flexgrid.formatItem.addHandler((s, e) => { // show row indices in row headers if (e.panel.cellType == wjcGrid.CellType.RowHeader) { e.cell.textContent = (e.row + 1).toString(); } }); flexgrid.scrollPositionChanged.addHandler(() => { let rng = flexgrid.viewRange; this.state.virtualOrderDetails.setWindow(rng.row, rng.row2); }); } } 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 OData and Virtual OData Binding</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 { height: 350px; } .wj-cell { border-color: #e0e0e0; } .wj-cell.wj-has-notes:after { position: absolute; content: ""; width: 0; right: 0; top: -10px; border: 10px solid transparent; border-right: 10px solid red; opacity: 0.5; } .wj-cell.wj-has-notes:hover:after { opacity: 1; } body { margin-bottom: 24pt; }