Sorting

FlexSheet can be sorted by any of its columns. The SortManager helps FlexSheet to manage the sort process. The following example uses SortManager to specify the order of the sorting, add or remove sort columns, and change the order of the sort columns.

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; }
(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.chart.webgl': 'npm:@grapecity/wijmo.chart.webgl/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', '@grapecity/wijmo.touch': 'npm:@grapecity/wijmo.touch/index.js', '@grapecity/wijmo.cloud': 'npm:@grapecity/wijmo.cloud/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);