Paging

The MultiRow control supports paging through the IPagedCollectionView interface, which is nearly identical to the one in .NET.

To enable paging, set the IPagedCollectionView.pageSize property to the number of items you want to display on each page, and provide a UI for navigating the pages.

import 'bootstrap.css'; import '@grapecity/wijmo.styles/wijmo.css'; import './styles.css'; import * as wjCore from '@grapecity/wijmo'; import * as wjMultiRow from '@grapecity/wijmo.grid.multirow'; import { generateAppData } from './data'; // document.readyState === 'complete' ? init() : window.onload = init; // function init() { let appData = generateAppData(); let pagedOrders = appData.pagedOrders; let pagingMultirow = new wjMultiRow.MultiRow('#pageMultirow', { itemsSource: pagedOrders, layoutDefinition: appData.ldThreeLines }); // paging buttons document.getElementById('firstBtn').addEventListener('click', function (e) { pagedOrders.moveToFirstPage(); }); document.getElementById('previousBtn').addEventListener('click', function (e) { pagedOrders.moveToPreviousPage(); }); document.getElementById('nextBtn').addEventListener('click', function (e) { pagedOrders.moveToNextPage(); }); document.getElementById('lastBtn').addEventListener('click', function (e) { pagedOrders.moveToLastPage(); }); // update page text now and when the current page changes updatePageText(); pagedOrders.collectionChanged.addHandler(function () { updatePageText(); }); pagedOrders.pageChanged.addHandler(function () { updatePageText(); }); function updatePageText() { var text = wjCore.format('{index:n0} / {count:n0}', { index: pagedOrders.pageIndex + 1, count: pagedOrders.pageCount }); wjCore.setText(document.querySelector('#numBtn'), text); } }
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <title>GrapeCity Wijmo MultiRow Paging</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 id="pageMultirow"></div> <div class="btn-group"> <button type="button" class="btn" id="firstBtn"> <span class="glyphicon glyphicon-fast-backward"></span> </button> <button type="button" class="btn" id="previousBtn"> <span class="glyphicon glyphicon-step-backward"></span> </button> <button type="button" class="btn" id="numBtn" disabled style="width:100px"></button> <button type="button" class="btn" id="nextBtn"> <span class="glyphicon glyphicon-step-forward"></span> </button> <button type="button" class="btn" id="lastBtn"> <span class="glyphicon glyphicon-fast-forward"></span> </button> </div> </div> </body> </html>
import * as wjCore from '@grapecity/wijmo'; import * as wjGrid from '@grapecity/wijmo.grid'; export function generateAppData() { // create some data let appData = {}, customers = [], firstNames = 'Aaron,Paul,John,Mark,Sue,Tom,Bill,Joe,Tony,Brad,Frank,Chris,Pat'.split(','), lastNames = 'Smith,Johnson,Richards,Bannon,Wong,Peters,White,Brown,Adams,Jennings'.split(','), cities = 'York,Paris,Rome,Cairo,Florence,Sidney,Hamburg,Vancouver'.split(','), states = 'SP,RS,RN,SC,CS,RT,BC'.split(','); for (let i = 0; i < 50; i++) { let first = firstNames[randBetween(0, firstNames.length - 1)], last = lastNames[randBetween(0, lastNames.length - 1)]; customers.push({ id: i, name: first + ' ' + last, address: randBetween(100, 10000) + ' ' + lastNames[randBetween(0, lastNames.length - 1)] + ' St.', city: cities[randBetween(0, cities.length - 1)], state: states[randBetween(0, states.length - 1)], zip: wjCore.format('{p1:d5}-{p2:d3}', { p1: randBetween(10000, 99999), p2: randBetween(100, 999) }), email: first + '.' + last + '@gmail.com', phone: wjCore.format('{p1:d3}-{p2:d4}', { p1: randBetween(100, 999), p2: randBetween(1000, 9999) }) }); } let cityMap = new wjGrid.DataMap(cities); let shippers = [ { id: 0, name: 'Speedy Express', email: 'speedy@gmail.com', phone: '431-3234', express: true }, { id: 1, name: 'Flash Delivery', email: 'flash@gmail.com', phone: '431-6563', express: true }, { id: 2, name: 'Logitrax', email: 'logitrax@gmail.com', phone: '431-3981', express: false }, { id: 3, name: 'Acme Inc', email: 'acme@gmail.com', phone: '431-3113', express: false } ]; let orders = []; let today = new Date(); for (let i = 0; i < 20; i++) { let shipped = wjCore.DateTime.addDays(today, -randBetween(1, 3000)); orders.push({ id: i, date: wjCore.DateTime.addDays(shipped, -randBetween(1, 5)), shippedDate: shipped, amount: randBetween(10000, 500000) / 100, customer: customers[randBetween(0, customers.length - 1)], shipper: shippers[randBetween(0, shippers.length - 1)] }); } function randBetween(min, max) { return Math.floor(Math.random() * (max - min + 1) + min); } // expose orders CollectionView to the app appData.orders = new wjCore.CollectionView(orders); // expose grouped orders CollectionView to the app appData.groupedOrders = new wjCore.CollectionView(orders, { groupDescriptions: [ 'customer.city' ] }); // expose paged orders CollectionView to the app appData.pagedOrders = new wjCore.CollectionView(orders, { pageSize: 4 }); // expose addNew oders CollectionView to the app appData.addNewOrders = new wjCore.CollectionView(orders, { newItemCreator: function () { return { customer: {}, shipper: {} }; }, }); appData.addNewOrders.moveCurrentToLast(); // refresh views when data source changes let ordersRefreshing = false; appData.orders.collectionChanged.addHandler(function () { ordersRefreshing = true; if (!pagedOrdersRefreshing) { appData.pagedOrders.refresh(); } if (!groupedOrdersRefreshing) { appData.groupedOrders.refresh(); } if (!addNewOrdersRefreshing) { appData.addNewOrders.refresh(); } ordersRefreshing = false; }); // addNew orders let addNewOrdersRefreshing = false; appData.addNewOrders.collectionChanged.addHandler(function () { addNewOrdersRefreshing = true; if (!ordersRefreshing) { appData.orders.refresh(); } if (!pagedOrdersRefreshing) { appData.pagedOrders.refresh(); } if (!groupedOrdersRefreshing) { appData.groupedOrders.refresh(); } addNewOrdersRefreshing = false; }); // grouped orders let groupedOrdersRefreshing = false; appData.groupedOrders.collectionChanged.addHandler(function () { groupedOrdersRefreshing = true; if (!ordersRefreshing) { appData.orders.refresh(); } if (!pagedOrdersRefreshing) { appData.pagedOrders.refresh(); } if (!addNewOrdersRefreshing) { appData.addNewOrders.refresh(); } groupedOrdersRefreshing = false; }); // paged orders let pagedOrdersRefreshing = false; appData.pagedOrders.collectionChanged.addHandler(function () { pagedOrdersRefreshing = true; if (!ordersRefreshing) { appData.orders.refresh(); } if (!addNewOrdersRefreshing) { appData.addNewOrders.refresh(); } if (!groupedOrdersRefreshing) { appData.groupedOrders.refresh(); } pagedOrdersRefreshing = false; }); // sample layout definitions appData.ldOneLine = [ { cells: [{ binding: 'id', header: 'ID', cssClass: 'id', isReadOnly: true }] }, { cells: [{ binding: 'date', header: 'Ordered' }] }, { cells: [{ binding: 'shippedDate', header: 'Shipped' }] }, { cells: [{ binding: 'amount', header: 'Amount', format: 'c', cssClass: 'amount' }] }, { cells: [{ binding: 'customer.name', header: 'Customer' }] }, { cells: [{ binding: 'customer.address', header: 'Address', wordWrap: true }] }, { cells: [{ binding: 'customer.city', header: 'City', dataMap: cityMap }] }, { cells: [{ binding: 'customer.state', header: 'State', width: 45 }] }, { cells: [{ binding: 'customer.zip', header: 'Zip' }] }, { cells: [{ binding: 'customer.email', header: 'Customer Email', cssClass: 'email' }] }, { cells: [{ binding: 'customer.phone', header: 'Customer Phone' }] }, { cells: [{ binding: 'shipper.name', header: 'Shipper' }] }, { cells: [{ binding: 'shipper.email', header: 'Shipper Email', cssClass: 'email' }] }, { cells: [{ binding: 'shipper.phone', header: 'Shipper Phone' }] }, { cells: [{ binding: 'shipper.express', header: 'Express' }] } ]; appData.ldTwoLines = [ { header: 'Order', colspan: 2, cells: [ { binding: 'id', header: 'ID', cssClass: 'id', isReadOnly: true }, { binding: 'date', header: 'Ordered' }, { binding: 'amount', header: 'Amount', format: 'c', cssClass: 'amount' }, { binding: 'shippedDate', header: 'Shipped' } ] }, { header: 'Customer', colspan: 3, cells: [ { binding: 'customer.name', header: 'Name' }, { binding: 'customer.email', header: 'EMail', colspan: 2, cssClass: 'email' }, { binding: 'customer.address', header: 'Address' }, { binding: 'customer.city', header: 'City', dataMap: cityMap }, { binding: 'customer.state', header: 'State', width: 45 } ] }, { header: 'Shipper', cells: [ { binding: 'shipper.name', header: 'Shipper', colspan: 2 }, { binding: 'shipper.email', header: 'EMail', cssClass: 'email' }, { binding: 'shipper.express', header: 'Express' } ] } ]; appData.ldThreeLines = [ { header: 'Order', colspan: 2, cells: [ { binding: 'id', header: 'ID', colspan: 2, cssClass: 'id' }, { binding: 'amount', header: 'Amount', format: 'c', colspan: 2, cssClass: 'amount' }, { binding: 'date', header: 'Ordered' }, { binding: 'shippedDate', header: 'Shipped' } ] }, { header: 'Customer', colspan: 3, cells: [ { binding: 'customer.name', header: 'Name' }, { binding: 'customer.email', header: 'EMail', colspan: 2, cssClass: 'email' }, { binding: 'customer.address', header: 'Address', colspan: 2 }, { binding: 'customer.phone', header: 'Phone' }, { binding: 'customer.city', header: 'City', dataMap: cityMap }, { binding: 'customer.state', header: 'State', width: 45 }, { binding: 'customer.zip', header: 'Zip' }, ] }, { header: 'Shipper', cells: [ { binding: 'shipper.name', header: 'Shipper' }, { binding: 'shipper.email', header: 'EMail', cssClass: 'email' }, { binding: 'shipper.express', header: 'Express' } ] } ]; appData.layoutDefs = new wjCore.CollectionView([ { name: 'Traditional', description: 'Traditional grid view, with one row per record. The user must scroll horizontally to see the whole record.', def: appData.ldOneLine }, { name: 'Compact', description: 'This view uses two rows per record. The layout is divided into three groups: order, customer, and shipper', def: appData.ldTwoLines }, { name: 'Detailed', description: 'This view uses three rows per record. The layout is divided into three groups: order, customer, and shipper', def: appData.ldThreeLines } ]); return appData; }
.wj-multirow { margin: 6px 0; max-height:800px }
(function (global) { System.config({ transpiler: 'plugin-babel', babelOptions: { es2015: true }, meta: { '*.css': { loader: 'css' } }, paths: { // paths serve as alias 'npm:': 'node_modules/' }, // map tells the System loader where to look for things map: { 'jszip': 'npm:jszip/dist/jszip.js', '@grapecity/wijmo': 'npm:@grapecity/wijmo/index.js', '@grapecity/wijmo.input': 'npm:@grapecity/wijmo.input/index.js', '@grapecity/wijmo.styles': 'npm:@grapecity/wijmo.styles', '@grapecity/wijmo.cultures': 'npm:@grapecity/wijmo.cultures', '@grapecity/wijmo.chart': 'npm:@grapecity/wijmo.chart/index.js', '@grapecity/wijmo.chart.analytics': 'npm:@grapecity/wijmo.chart.analytics/index.js', '@grapecity/wijmo.chart.animation': 'npm:@grapecity/wijmo.chart.animation/index.js', '@grapecity/wijmo.chart.annotation': 'npm:@grapecity/wijmo.chart.annotation/index.js', '@grapecity/wijmo.chart.finance': 'npm:@grapecity/wijmo.chart.finance/index.js', '@grapecity/wijmo.chart.finance.analytics': 'npm:@grapecity/wijmo.chart.finance.analytics/index.js', '@grapecity/wijmo.chart.hierarchical': 'npm:@grapecity/wijmo.chart.hierarchical/index.js', '@grapecity/wijmo.chart.interaction': 'npm:@grapecity/wijmo.chart.interaction/index.js', '@grapecity/wijmo.chart.radar': 'npm:@grapecity/wijmo.chart.radar/index.js', '@grapecity/wijmo.chart.render': 'npm:@grapecity/wijmo.chart.render/index.js', '@grapecity/wijmo.gauge': 'npm:@grapecity/wijmo.gauge/index.js', '@grapecity/wijmo.grid': 'npm:@grapecity/wijmo.grid/index.js', '@grapecity/wijmo.grid.detail': 'npm:@grapecity/wijmo.grid.detail/index.js', '@grapecity/wijmo.grid.filter': 'npm:@grapecity/wijmo.grid.filter/index.js', '@grapecity/wijmo.grid.search': 'npm:@grapecity/wijmo.grid.search/index.js', '@grapecity/wijmo.grid.grouppanel': 'npm:@grapecity/wijmo.grid.grouppanel/index.js', '@grapecity/wijmo.grid.multirow': 'npm:@grapecity/wijmo.grid.multirow/index.js', '@grapecity/wijmo.grid.transposed': 'npm:@grapecity/wijmo.grid.transposed/index.js', '@grapecity/wijmo.grid.pdf': 'npm:@grapecity/wijmo.grid.pdf/index.js', '@grapecity/wijmo.grid.sheet': 'npm:@grapecity/wijmo.grid.sheet/index.js', '@grapecity/wijmo.grid.xlsx': 'npm:@grapecity/wijmo.grid.xlsx/index.js', '@grapecity/wijmo.grid.selector': 'npm:@grapecity/wijmo.grid.selector/index.js', '@grapecity/wijmo.grid.cellmaker': 'npm:@grapecity/wijmo.grid.cellmaker/index.js', '@grapecity/wijmo.nav': 'npm:@grapecity/wijmo.nav/index.js', '@grapecity/wijmo.odata': 'npm:@grapecity/wijmo.odata/index.js', '@grapecity/wijmo.olap': 'npm:@grapecity/wijmo.olap/index.js', '@grapecity/wijmo.pdf': 'npm:@grapecity/wijmo.pdf/index.js', '@grapecity/wijmo.viewer': 'npm:@grapecity/wijmo.viewer/index.js', '@grapecity/wijmo.xlsx': 'npm:@grapecity/wijmo.xlsx/index.js', '@grapecity/wijmo.undo': 'npm:@grapecity/wijmo.undo/index.js', '@grapecity/wijmo.interop.grid': 'npm:@grapecity/wijmo.interop.grid/index.js', 'jszip': 'npm:jszip/dist/jszip.js', 'bootstrap.css': 'npm:bootstrap/dist/css/bootstrap.min.css', 'css': 'npm:systemjs-plugin-css/css.js', 'plugin-babel': 'npm:systemjs-plugin-babel/plugin-babel.js', 'systemjs-babel-build':'npm:systemjs-plugin-babel/systemjs-babel-browser.js' }, // packages tells the System loader how to load when no filename and/or no extension packages: { src: { defaultExtension: 'js' }, "node_modules": { defaultExtension: 'js' }, } }); })(this);