排序

FlexSheet可以按其任何列进行排序。

SortManager 帮助FlexSheet管理排序过程。 以下示例使用SortManager指定排序顺序,添加或删除排序列,以及更改排序列的顺序。

import 'bootstrap.css'; import '@grapecity/wijmo.styles/wijmo.css'; import './styles.css'; import * as wjCore from '@grapecity/wijmo'; import * as wjGrid from '@grapecity/wijmo.grid'; import * as wjFlexSheet from '@grapecity/wijmo.grid.sheet'; import { getData, getCountries, getProducts } from './data'; // document.readyState === 'complete' ? init() : window.onload = init; // function init() { let sortSheet = new wjFlexSheet.FlexSheet('#sortSheet'); sortSheet.addBoundSheet('Country', getData(50)); sortSheet.deferUpdate(() => { let column = sortSheet.columns.getColumn('countryId'); if (column && !column.dataMap) { column.dataMap = buildDataMap(getCountries()); } column = sortSheet.columns.getColumn('productId'); if (column && !column.dataMap) { column.dataMap = buildDataMap(getProducts()); } column = sortSheet.columns.getColumn('amount'); if (column) { column.format = 'c2'; } }); let sortManager = sortSheet.sortManager; updateSortTable(); onClick('addLevel', addSortLevel); onClick('delLevel', deleteSortLevel); onClick('copyLevel', copySortLevel); onClick('moveup', () => { moveSortLevel(-1); }); onClick('movedown', () => { moveSortLevel(1); }); onClick('commitSort', commitSort); onClick('cancelSort', cancelSort); sortSheet.selectedSheetChanged.addHandler(() => { updateSortTable(); }); sortManager.sortDescriptions.collectionChanged.addHandler(() => { updateSortTable(); }); sortManager.sortDescriptions.currentChanged.addHandler(() => { updateSortTable(); }); function updateSortTable() { let sortTableBody = document.querySelector('#sortTable tbody'), tRows = '', columns = getColumns(), sortItem; for (let index = 0; index < sortManager.sortDescriptions.itemCount; index++) { sortItem = sortManager.sortDescriptions.items[index]; tRows += '<tr class="' + (sortManager.sortDescriptions.currentPosition === index ? 'success"' : '"') + '><td>' + updateColumnSelect(columns, sortItem) + '</td>'; tRows += '<td><select class="form-control" onchange=""><option value="0"' + ((!sortItem || sortItem.ascending) ? ' selected="selected">' : '>') + 'Ascending</option>' + '<option value="1"' + ((sortItem && !sortItem.ascending) ? ' selected="selected">' : '>') + 'Descending</option></select></td></tr>'; } sortTableBody.innerHTML = tRows; let sortRows = sortTableBody.querySelectorAll('tr'); for (let rowIndex = 0; rowIndex < sortRows.length; rowIndex++) { sortRows[rowIndex].addEventListener('click', () => { sortManager.sortDescriptions.moveCurrentToPosition(rowIndex); updateActiveRow(); }); } let columnSelects = sortTableBody.querySelectorAll('tr td:first-child select'), ascendingSelects = sortTableBody.querySelectorAll('tr td:last-child select'); for (let sortIndex = 0; sortIndex < columnSelects.length; sortIndex++) { sortItem = sortManager.sortDescriptions.items[sortIndex]; columnSelects[sortIndex].addEventListener('change', (e) => { sortItem.columnIndex = e.target.selectedIndex - 1; }); ascendingSelects[sortIndex].addEventListener('change', (e) => { sortItem.ascending = e.target.selectedIndex === 0; }); } updateMoveButtonState(); } function updateActiveRow() { let sortTableBody = document.querySelector('#sortTable tbody'), sortRows = sortTableBody.querySelectorAll('tr'); removeSuccessClass(sortRows); wjCore.addClass(sortRows[sortManager.sortDescriptions.currentPosition], 'success'); } function removeSuccessClass(sortRows) { for (let rowIndex = 0; rowIndex < sortRows.length; rowIndex++) { wjCore.removeClass(sortRows[rowIndex], 'success'); } } function updateColumnSelect(columns, sortItem) { let colSelect = '<select class="form-control"><option value=-1></option>'; for (let index = 0; index < columns.length; index++) { colSelect += '<option ' + ((sortItem && sortItem.columnIndex === index) ? 'selected="selected" ' : '') + ' value="' + index + '">' + columns[index] + '</option>'; } colSelect += '</select>'; return colSelect; } function updateMoveButtonState() { let moveupBtn = document.querySelector('#moveup'), movedownBtn = document.querySelector('#movedown'); if (sortManager.sortDescriptions.currentPosition === 0) { moveupBtn.setAttribute('disabled', 'true'); } else { moveupBtn.removeAttribute('disabled'); } if (sortManager.sortDescriptions.currentPosition === sortManager.sortDescriptions.itemCount - 1) { movedownBtn.setAttribute('disabled', 'true'); } else { movedownBtn.removeAttribute('disabled'); } } // get the columns with the column header text for the column selection for sort setting. function getColumns() { var columns = [], i = 0; if (sortSheet) { for (; i < sortSheet.columns.length; i++) { columns.push('Column ' + wjFlexSheet.FlexSheet.convertNumberToAlpha(i)); } } return columns; } // commit the sorts function commitSort() { sortManager.commitSort(); } // cancel the sorts function cancelSort() { sortManager.cancelSort(); updateActiveRow(); } // add new sort level function addSortLevel() { sortManager.addSortLevel(); updateActiveRow(); } // delete current sort level function deleteSortLevel() { sortManager.deleteSortLevel(); updateActiveRow(); } // copy a new sort level by current sort level setting. function copySortLevel() { sortManager.copySortLevel(); updateActiveRow(); } // move the sort level function moveSortLevel(offset) { sortManager.moveSortLevel(offset); updateActiveRow(); } // build a data map from a string array using the indices as keys function buildDataMap(items) { let map = []; for (let i = 0; i < items.length; i++) { map.push({ key: i, value: items[i] }); } return new wjGrid.DataMap(map, 'key', 'value'); } ; function onClick(id, fn) { document.querySelector('#' + id).addEventListener('click', fn); } } <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <title>GrapeCity Wijmo FlexSheet Sorting</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="sortSheet"></div> <table id="sortTable" class="table table-bordered"> <thead> <tr> <th class="text-center">Column</th> <th class="text-center">Order</th> </tr> </thead> <tbody> </tbody> </table> <div class="btn-group"> <button id="addLevel" type="button" class="btn btn-default"> Add Level </button> <button id="delLevel" type="button" class="btn btn-default"> Delete Level </button> <button id="copyLevel" type="button" class="btn btn-default"> Copy Level </button> </div> <div class="btn-group"> <button id="moveup" type="button" class="btn btn-default"> <span class="glyphicon glyphicon-arrow-up"></span> </button> <button id="movedown" type="button" class="btn btn-default"> <span class="glyphicon glyphicon-arrow-down"></span> </button> </div> <div class="btn-group"> <button id="commitSort" type="button" class="btn btn-default">OK</button> <button id="cancelSort" type="button" class="btn btn-default">Cancel</button> </div> </div> </body> </html> let countries = ['US', 'Germany', 'UK', 'Japan', 'Italy', 'Greece'], products = ['Widget', 'Gadget', 'Doohickey']; export function getData(count) { let data = [], i = 0, countryId, productId; for (; i < count; i++) { countryId = Math.floor(Math.random() * countries.length); productId = Math.floor(Math.random() * products.length); data.push({ id: i, countryId: countryId, productId: productId, date: new Date(2014, i % 12, i % 28), amount: Math.random() * 10000, active: i % 4 === 0 }); } return data; } export function getCountries() { return countries; } export function getProducts() { return products; } .wj-flexsheet { height: 400px; margin: 6px 0; } import 'bootstrap.css'; import '@grapecity/wijmo.styles/wijmo.css'; import './styles.css'; import { Component, enableProdMode, NgModule, Inject } from '@angular/core'; import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; import { BrowserModule } from '@angular/platform-browser'; import { WjGridSheetModule } from '@grapecity/wijmo.angular2.grid.sheet'; import * as wjcGrid from '@grapecity/wijmo.grid'; import * as wjcSheet from '@grapecity/wijmo.grid.sheet'; import { DataService } from './app.data'; @Component({ selector: 'app-component', templateUrl: 'src/app.component.html' }) export class AppComponent { data: any[]; sortManager: wjcSheet.SortManager; columns: string[]; private _countries: string[]; private _products: string[]; constructor(@Inject(DataService) dataSvc: DataService) { this.data = dataSvc.getData(50); this._countries = dataSvc.countries; this._products = dataSvc.products; } initializeFlexSheet(flex: wjcSheet.FlexSheet) { flex.deferUpdate(() => { let column = flex.columns.getColumn('countryId'); if (column && !column.dataMap) { column.dataMap = this._buildDataMap(this._countries); } column = flex.columns.getColumn('productId'); if (column && !column.dataMap) { column.width = 100; column.dataMap = this._buildDataMap(this._products); } column = flex.columns.getColumn('amount'); if (column) { column.format = 'c2'; } this.sortManager = flex.sortManager; this.columns = this._getColumns(flex); }); flex.selectedSheetChanged.addHandler(() => { this.columns = this._getColumns(flex); if (!this.sortManager) { this.sortManager = flex.sortManager; } }); flex.columnChanged.addHandler(() => { this.columns = this._getColumns(flex); }); } // commit the sorts commitSort() { this.sortManager.commitSort(); }; // cancel the sorts cancelSort() { this.sortManager.cancelSort(); }; // add new sort level addSortLevel() { this.sortManager.addSortLevel(); }; // delete current sort level deleteSortLevel() { this.sortManager.deleteSortLevel(); }; // copy a new sort level by current sort level setting. copySortLevel() { this.sortManager.copySortLevel(); }; // move the sort level moveSortLevel(offset: number) { this.sortManager.moveSortLevel(offset); }; // apply column index property for sort item applySortColumnIndex(e: any, sortItem: wjcSheet.ColumnSortDescription) { sortItem.columnIndex = +e.target.value; } // apply asceding property for sort item applySortAscending(e: any, sortItem: wjcSheet.ColumnSortDescription) { if (e.target.value === 'true') { sortItem.ascending = true; } else { sortItem.ascending = false; } } // build a data map from a string array using the indices as keys private _buildDataMap(items: string[]) { let map = []; for (let i = 0; i < items.length; i++) { map.push({ key: i, value: items[i] }); } return new wjcGrid.DataMap(map, 'key', 'value'); } private _getColumns(flexSheet: wjcSheet.FlexSheet): string[] { let columns = [], i = 0; if (flexSheet) { for (; i < flexSheet.columns.length; i++) { columns.push('Column ' + wjcSheet.FlexSheet.convertNumberToAlpha(i)); } } return columns; } } @NgModule({ imports: [WjGridSheetModule, BrowserModule], providers: [DataService], 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 FlexSheet Sorting</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"> <!-- the flexsheet --> <wj-flex-sheet #flex (initialized)="initializeFlexSheet(flex)"> <wj-sheet [name]="'Country'" [(itemsSource)]="data"></wj-sheet> </wj-flex-sheet> <table class="table table-bordered"> <thead> <tr> <th class="text-center" style="width: 50%;">Column</th> <th class="text-center" style="width: 50%;">Order</th> </tr> </thead> <tbody *ngIf="sortManager"> <tr *ngFor="let sortItem of sortManager.sortDescriptions.items" (click)="sortManager.sortDescriptions.moveCurrentTo(sortItem)" [ngClass]="{success: sortItem === sortManager.sortDescriptions.currentItem}"> <td> <select class="form-control" (change)="applySortColumnIndex($event, sortItem)"> <option value=-1></option> <option *ngFor="let column of columns; let i = index" [selected]="i === sortItem.columnIndex" value={{i}}> {{column}} </option> </select> </td> <td> <select class="form-control" (change)="applySortAscending($event, sortItem)"> <option [value]="true" [selected]="sortItem.ascending">Ascending</option> <option [value]="false" [selected]="!sortItem.ascending">Descending</option> </select> </td> </tr> </tbody> </table> <div class="btn-group"> <button type="button" class="btn btn-default" (click)="addSortLevel()"> Add Level </button> <button type="button" class="btn btn-default" (click)="deleteSortLevel()"> Delete Level </button> <button type="button" class="btn btn-default" (click)="copySortLevel()"> Copy Level </button> </div> <div class="btn-group"> <button id="moveup" type="button" class="btn btn-default" [disabled]="sortManager && sortManager.sortDescriptions.currentPosition <= 0" (click)="moveSortLevel(-1)"> <span class="glyphicon glyphicon-arrow-up"></span> </button> <button id="movedown" type="button" class="btn btn-default" [disabled]="sortManager && sortManager.sortDescriptions.currentPosition >= sortManager.sortDescriptions.itemCount - 1" (click)="moveSortLevel(1)"> <span class="glyphicon glyphicon-arrow-down"></span> </button> </div> <div class="btn-group"> <button type="button" class="btn btn-default" (click)="commitSort()">OK</button> <button type="button" class="btn btn-default" (click)="cancelSort()">Cancel</button> </div> </div> import { Injectable } from '@angular/core'; @Injectable() export class DataService { countries = ['US', 'Germany', 'UK', 'Japan', 'Italy', 'Greece']; products = ['Widget', 'Gadget', 'Doohickey']; getData(count: number) { let data = [], i = 0, countryId, productId; for (; i < count; i++) { countryId = Math.floor(Math.random() * this.countries.length); productId = Math.floor(Math.random() * this.products.length); data.push({ id: i, countryId: countryId, productId: productId, date: new Date(2014, i % 12, i % 28), amount: Math.random() * 10000, active: i % 4 === 0 }); } return data; } } .wj-flexsheet { height: 400px; margin: 6px 0; } <template> <div class="container-fluid"> <!-- the flexsheet --> <wj-flex-sheet :initialized="initializeFlexSheet"> <wj-sheet :name="'Country'" :itemsSource="data"></wj-sheet> </wj-flex-sheet> <table class="table table-bordered"> <thead> <tr> <th class="text-center" style="width: 50%;">Column</th> <th class="text-center" style="width: 50%;">Order</th> </tr> </thead> <tbody v-if="sortManager"> <tr v-for="(sortItem,index) of sortManager.sortDescriptions.items" :key="index" @click="sortManager.sortDescriptions.moveCurrentTo(sortItem)" :class="{success: sortItem === sortManager.sortDescriptions.currentItem}" > <td> <select class="form-control" @change="applySortColumnIndex($event, sortItem)" > <option value="-1"></option> <option v-for="(column,i) of columns" :key="i" :selected="i === sortItem.columnIndex" :value="i" >{{column}}</option> </select> </td> <td> <select class="form-control" @change="applySortAscending($event, sortItem)"> <option :value="true" :selected="sortItem.ascending">Ascending</option> <option :value="false" :selected="!sortItem.ascending">Descending</option> </select> </td> </tr> </tbody> </table> <div class="btn-group"> <button type="button" class="btn btn-default" @click="addSortLevel">Add Level</button> <button type="button" class="btn btn-default" @click="deleteSortLevel">Delete Level</button> <button type="button" class="btn btn-default" @click="copySortLevel">Copy Level</button> </div> <div class="btn-group"> <button id="moveup" type="button" class="btn btn-default" :disabled="sortManager && sortManager.sortDescriptions.currentPosition <= 0" @click="moveSortLevel(-1)" > <span class="glyphicon glyphicon-arrow-up"></span> </button> <button id="movedown" type="button" class="btn btn-default" :disabled="sortManager && sortManager.sortDescriptions.currentPosition >= sortManager.sortDescriptions.itemCount - 1" @click="moveSortLevel(1)" > <span class="glyphicon glyphicon-arrow-down"></span> </button> </div> <div class="btn-group"> <button type="button" class="btn btn-default" @click="commitSort">OK</button> <button type="button" class="btn btn-default" @click="cancelSort">Cancel</button> </div> </div> </template> <script> import "@grapecity/wijmo.styles/wijmo.css"; import "bootstrap.css"; import Vue from "vue"; import '@grapecity/wijmo.vue2.grid.sheet'; import * as wjcGrid from '@grapecity/wijmo.grid'; import * as wjcSheet from '@grapecity/wijmo.grid.sheet'; import { getData, getCountries, getProducts } from "./data"; let App = Vue.extend({ name: "app", data: function() { return { data: getData(50), sortManager: null, columns: [], countries: getCountries(), products: getProducts() }; }, methods: { initializeFlexSheet: function(flex) { flex.deferUpdate(() => { let column = flex.columns.getColumn("countryId"); if (column && !column.dataMap) { column.dataMap = this._buildDataMap(this.countries); } column = flex.columns.getColumn("productId"); if (column && !column.dataMap) { column.width = 100; column.dataMap = this._buildDataMap(this.products); } column = flex.columns.getColumn("amount"); if (column) { column.format = "c2"; } this.sortManager = flex.sortManager; this.columns = this._getColumns(flex); }); flex.selectedSheetChanged.addHandler(() => { this.columns = this._getColumns(flex); if (!this.sortManager) { this.sortManager = flex.sortManager; } }); flex.columnChanged.addHandler(() => { this.columns = this._getColumns(flex); }); }, // commit the sorts commitSort: function() { this.sortManager.commitSort(); }, // cancel the sorts cancelSort: function() { this.sortManager.cancelSort(); }, // add new sort level addSortLevel: function() { this.sortManager.addSortLevel(); }, // delete current sort level deleteSortLevel: function() { this.sortManager.deleteSortLevel(); }, // copy a new sort level by current sort level setting. copySortLevel: function() { this.sortManager.copySortLevel(); }, // move the sort level moveSortLevel: function(offset) { this.sortManager.moveSortLevel(offset); }, // apply column index property for sort item applySortColumnIndex: function(e, sortItem) { sortItem.columnIndex = e.target.value; }, // apply asceding property for sort item applySortAscending: function(e, sortItem) { if (e.target.value === "true") { sortItem.ascending = true; } else { sortItem.ascending = false; } }, // build a data map from a string array using the indices as keys _buildDataMap: function(items) { let map = []; for (let i = 0; i < items.length; i++) { map.push({ key: i, value: items[i] }); } return new wjcGrid.DataMap(map, "key", "value"); }, _getColumns: function(flexSheet) { let columns = [], i = 0; if (flexSheet) { for (; i < flexSheet.columns.length; i++) { columns.push( "Column " + wjcSheet.FlexSheet.convertNumberToAlpha(i) ); } } return columns; } } }); new Vue({ render: h => h(App) }).$mount("#app"); </script> <style> .container-fluid .wj-flexsheet { height: 400px; margin: 6px 0; } </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/jszip/dist/jszip.js"></script> <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> let countries = ['US', 'Germany', 'UK', 'Japan', 'Italy', 'Greece'], products = ['Widget', 'Gadget', 'Doohickey']; export function getData(count) { let data = [], i = 0, countryId, productId; for (; i < count; i++) { countryId = Math.floor(Math.random() * countries.length); productId = Math.floor(Math.random() * products.length); data.push({ id: i, countryId: countryId, productId: productId, date: new Date(2014, i % 12, i % 28), amount: Math.random() * 10000, active: i % 4 === 0 }); } return data; } export function getCountries() { return countries; } export function getProducts() { return products; } import './app.css'; import 'bootstrap.css'; import '@grapecity/wijmo.styles/wijmo.css'; // import * as React from 'react'; import * as ReactDOM from 'react-dom'; // import * as wjcSheet from "@grapecity/wijmo.grid.sheet"; import * as wjcGrid from "@grapecity/wijmo.grid"; import * as wjGridSheet from "@grapecity/wijmo.react.grid.sheet"; import { getData, getCountries, getProducts } from "./data"; class App extends React.Component { constructor(props) { super(props); this.state = { data: getData(50), sortManager: null, columns: [], countries: getCountries(), products: getProducts() }; } initializeFlexSheet(flex) { flex.deferUpdate(() => { let column = flex.columns.getColumn("countryId"); if (column && !column.dataMap) { column.dataMap = this._buildDataMap(this.state.countries); } column = flex.columns.getColumn("productId"); if (column && !column.dataMap) { column.width = 100; column.dataMap = this._buildDataMap(this.state.products); } column = flex.columns.getColumn("amount"); if (column) { column.format = "c2"; } this.setState({ sortManager: flex.sortManager, columns: this._getColumns(flex) }); }); flex.selectedSheetChanged.addHandler(() => { this.setState({ columns: this._getColumns(flex) }); if (!this.state.sortManager) { this.setState({ sortManage: flex.sortManager, }); } }); flex.columnChanged.addHandler(() => { this.setState({ columns: this._getColumns(flex) }); }); } // commit the sorts commitSort() { this.state.sortManager.commitSort(); this.forceUpdate(); } // cancel the sorts cancelSort() { this.state.sortManager.cancelSort(); this.forceUpdate(); } // add new sort level addSortLevel() { this.state.sortManager.addSortLevel(); this.forceUpdate(); } // delete current sort level deleteSortLevel() { this.state.sortManager.deleteSortLevel(); this.forceUpdate(); } // copy a new sort level by current sort level setting. copySortLevel() { this.state.sortManager.copySortLevel(); this.forceUpdate(); } // move the sort level moveSortLevel(offset) { this.state.sortManager.moveSortLevel(offset); this.forceUpdate(); } // apply column index property for sort item applySortColumnIndex(e, sortItem) { sortItem.columnIndex = e.target.value; } // apply asceding property for sort item applySortAscending(e, sortItem) { if (e.target.value === "true") { sortItem.ascending = true; } else { sortItem.ascending = false; } } // build a data map from a string array using the indices as keys _buildDataMap(items) { let map = []; for (let i = 0; i < items.length; i++) { map.push({ key: i, value: items[i] }); } return new wjcGrid.DataMap(map, "key", "value"); } _getColumns(flexSheet) { let columns = [], i = 0; if (flexSheet) { for (; i < flexSheet.columns.length; i++) { columns.push("Column " + wjcSheet.FlexSheet.convertNumberToAlpha(i)); } } return columns; } renderOption(sortItem, column, i) { return (<option key={i} selected={(i === sortItem.columnIndex)} value={i}>{column}</option>); } getClass(sortItem) { let flag = (sortItem === this.state.sortManager.sortDescriptions.currentItem); if (flag) { return "success"; } return ""; } onTrClick(sortItem) { this.state.sortManager.sortDescriptions.moveCurrentTo(sortItem); this.forceUpdate(); } renderTr(sortItem, i) { let option = []; this.state.columns.forEach((column, i) => { option.push(this.renderOption(sortItem, column, i)); }); return (<tr key={i} onClick={() => this.onTrClick(sortItem)} className={this.getClass(sortItem)}> <td> <select className="form-control" onChange={(e) => this.applySortColumnIndex(e, sortItem)}> <option value="-1"></option> {option} </select> </td> <td> <select className="form-control" onChange={(e) => this.applySortAscending(e, sortItem)}> <option value="true" selected={sortItem.ascending}>Ascending</option> <option value="false" selected={!sortItem.ascending}>Descending</option> </select> </td> </tr>); } renderTbody() { if (!this.state.sortManager) { return; } let tr = []; this.state.sortManager.sortDescriptions.items.forEach((sortItem, i) => { tr.push(this.renderTr(sortItem, i)); }); return (<tbody> {tr} </tbody>); } render() { return (<div className="container-fluid"> <wjGridSheet.FlexSheet initialized={this.initializeFlexSheet.bind(this)}> <wjGridSheet.Sheet name="Country" itemsSource={this.state.data}></wjGridSheet.Sheet> </wjGridSheet.FlexSheet> <table className="table table-bordered"> <thead> <tr> <th className="text-center" style={{ width: "50%" }}>Column</th> <th className="text-center" style={{ width: "50%" }}>Order</th> </tr> </thead> {this.renderTbody()} </table> <div className="btn-group"> <button type="button" className="btn btn-default" onClick={this.addSortLevel.bind(this)}>Add Level</button> <button type="button" className="btn btn-default" onClick={this.deleteSortLevel.bind(this)}>Delete Level</button> <button type="button" className="btn btn-default" onClick={this.copySortLevel.bind(this)}>Copy Level</button> </div> <div className="btn-group"> <button id="moveup" type="button" className="btn btn-default" disabled={this.state.sortManager && this.state.sortManager.sortDescriptions.currentPosition <= 0} onClick={() => this.moveSortLevel(-1)}> <span className="glyphicon glyphicon-arrow-up"></span> </button> <button id="movedown" type="button" className="btn btn-default" disabled={this.state.sortManager && this.state.sortManager.sortDescriptions.currentPosition >= this.state.sortManager.sortDescriptions.itemCount - 1} onClick={() => this.moveSortLevel(1)}> <span className="glyphicon glyphicon-arrow-down"></span> </button> </div> <div className="btn-group"> <button type="button" className="btn btn-default" onClick={this.commitSort.bind(this)}>OK</button> <button type="button" className="btn btn-default" onClick={this.cancelSort.bind(this)}>Cancel</button> </div> </div>); } } 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>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'); </script> </head> <body> <div id="app"></div> </body> </html> .container-fluid .wj-flexsheet { height: 400px; margin: 6px 0; } let countries = ['US', 'Germany', 'UK', 'Japan', 'Italy', 'Greece'], products = ['Widget', 'Gadget', 'Doohickey']; export function getData(count) { let data = [], i = 0, countryId, productId; for (; i < count; i++) { countryId = Math.floor(Math.random() * countries.length); productId = Math.floor(Math.random() * products.length); data.push({ id: i, countryId: countryId, productId: productId, date: new Date(2014, i % 12, i % 28), amount: Math.random() * 10000, active: i % 4 === 0 }); } return data; } export function getCountries() { return countries; } export function getProducts() { return products; }