diff --git a/examples/js/sort/custom-sort-table-has-footer.js b/examples/js/sort/custom-sort-table-has-footer.js new file mode 100644 index 000000000..1f606c200 --- /dev/null +++ b/examples/js/sort/custom-sort-table-has-footer.js @@ -0,0 +1,62 @@ +/* eslint max-len: 0 */ +import React from 'react'; +import { BootstrapTable, TableHeaderColumn } from 'react-bootstrap-table'; + + +const products = []; + +function addProducts(quantity) { + let value; + const startId = products.length; + let total = 0; + for (let i = 0; i < quantity; i++) { + const id = startId + i; + value = 2100 + Math.floor(Math.random() * 100) + 1; + products.push({ + id: id, + name: 'Item name ' + id, + cost: value + }); + total += value; + } + /* add footer row with total calculations */ + products.push({ + id: products.length, + name: 'Total', + cost: total + }); +} + +addProducts(20); + +function revertSortFunc(a, b, order) { // order is desc or asc + + if (order === 'desc') { + return a.cost - b.cost; + } else { + return b.cost - a.cost; + } +} +/* custom function for string sorting */ +function sortStrings(a, b, order) { + if (order === 'desc') { + return a.name.toLowerCase().localeCompare(b.name.toLowerCase()); + } else { + return b.name.toLowerCase().localeCompare(a.name.toLowerCase()); + } +} + +export default class CustomSortTableHasFooter extends React.Component { + render() { + const options = { + hasFooter: true + }; + return ( + + Product ID + Product Name + Product Cost + + ); + } +} diff --git a/examples/js/sort/demo.js b/examples/js/sort/demo.js index 3db013a66..b75e95ff1 100755 --- a/examples/js/sort/demo.js +++ b/examples/js/sort/demo.js @@ -5,6 +5,7 @@ import MultiSortTable from './multi-sort-table'; import DefaultSortTable from './default-sort-table'; import ExternalSort from './manage-sort-external-table'; import CustomSortTable from './custom-sort-table'; +import CustomSortTableHasFooter from './custom-sort-table-has-footer'; import CustomSortWithExtraDataTable from './custom-sort-with-extra-data-table'; import ReusableCustomSortTable from './reusable-custom-sort-table'; import SortHookTable from './sort-hook-table'; @@ -70,6 +71,15 @@ class Demo extends React.Component { +
+
+
Customize Table Sort Example With Footer
+
+
Source in /examples/js/sort/custom-sort-table-has-footer.js
+ +
+
+
Customize Table Sort With Extra Data Example
diff --git a/src/BootstrapTable.js b/src/BootstrapTable.js index 50ce8b923..dc47d31a7 100644 --- a/src/BootstrapTable.js +++ b/src/BootstrapTable.js @@ -23,7 +23,6 @@ class BootstrapTable extends Component { this.isIE = document.documentMode; } this.store = new TableDataStore(this.props.data ? this.props.data.slice() : []); - this.isVerticalScroll = false; this.initTable(this.props); if (this.props.selectRow && this.props.selectRow.selected) { @@ -98,7 +97,8 @@ class BootstrapTable extends Component { colInfos: this.colInfos, multiColumnSearch: props.multiColumnSearch, multiColumnSort: props.multiColumnSort, - remote: this.props.remote + remote: this.props.remote, + hasFooter: this.props.options.hasFooter }); } @@ -225,6 +225,7 @@ class BootstrapTable extends Component { const sortList = this.store.getSortInfo(); const sortField = options.sortName; const sortOrder = options.sortOrder; + if (sortField && sortOrder) { this.store.setSortInfo(sortOrder, sortField); this.store.sort(); @@ -381,6 +382,7 @@ class BootstrapTable extends Component { expandableRow={ this.props.expandableRow } expandRowBgColor={ this.props.options.expandRowBgColor } expandBy={ this.props.options.expandBy || Const.EXPAND_BY_ROW } + hasFooter={ this.props.options.hasFooter } columns={ columns } trClassName={ this.props.trClassName } striped={ this.props.striped } @@ -1152,7 +1154,7 @@ class BootstrapTable extends Component { const scrollBarWidth = isScroll ? Util.getScrollBarWidth() : 0; if (firstRow && this.store.getDataNum()) { - if (isScroll || this.isVerticalScroll !== isScroll) { + if (isScroll) { const cells = firstRow.childNodes; for (let i = 0; i < cells.length; i++) { const cell = cells[i]; @@ -1190,7 +1192,6 @@ class BootstrapTable extends Component { } }); } - this.isVerticalScroll = isScroll; } _adjustHeight() { @@ -1271,7 +1272,7 @@ BootstrapTable.propTypes = { Const.ROW_SELECT_MULTI ]), customComponent: PropTypes.func, - bgColor: PropTypes.oneOfType([ PropTypes.string, PropTypes.func ]), + bgColor: PropTypes.string, selected: PropTypes.array, onSelect: PropTypes.func, onSelectAll: PropTypes.func, @@ -1292,6 +1293,7 @@ BootstrapTable.propTypes = { }), insertRow: PropTypes.bool, deleteRow: PropTypes.bool, + hasFooter: PropTypes.bool, search: PropTypes.bool, columnFilter: PropTypes.bool, trClassName: PropTypes.any, @@ -1416,6 +1418,7 @@ BootstrapTable.defaultProps = { pagination: false, printable: false, keyBoardNav: false, + hasFooter: false, searchPlaceholder: undefined, selectRow: { mode: Const.ROW_SELECT_NONE, diff --git a/src/store/TableDataStore.js b/src/store/TableDataStore.js index c0c74d29d..25671685d 100644 --- a/src/store/TableDataStore.js +++ b/src/store/TableDataStore.js @@ -30,6 +30,7 @@ export class TableDataStore { this.remote = props.remote; this.multiColumnSearch = props.multiColumnSearch; this.multiColumnSort = props.multiColumnSort; + this.hasFooter = props.hasFooter; } clean() { @@ -155,7 +156,7 @@ export class TableDataStore { let currentDisplayData = this.getCurrentDisplayData(); currentDisplayData = this._sort(currentDisplayData); - + this.data = currentDisplayData; return this; } @@ -570,44 +571,84 @@ export class TableDataStore { if (this.sortList.length === 0 || typeof(this.sortList[0]) === 'undefined') { return arr; } - - arr.sort((a, b) => { - let result = 0; - - for (let i = 0; i < this.sortList.length; i++) { - const sortDetails = this.sortList[i]; - const isDesc = sortDetails.order.toLowerCase() === Const.SORT_DESC; - - const { sortFunc, sortFuncExtraData } = this.colInfos[sortDetails.sortField]; - - if (sortFunc) { - result = sortFunc(a, b, sortDetails.order, sortDetails.sortField, sortFuncExtraData); - } else { - const valueA = a[sortDetails.sortField] === null ? '' : a[sortDetails.sortField]; - const valueB = b[sortDetails.sortField] === null ? '' : b[sortDetails.sortField]; - if (isDesc) { - if (typeof valueB === 'string') { - result = valueB.localeCompare(valueA); - } else { - result = valueA > valueB ? -1 : ((valueA < valueB) ? 1 : 0); - } + if (this.hasFooter) { + /* if it has hasFooter propery enabled*/ + const lastElem = arr[ arr.length - 1]; + /* sort all elements except the last one */ + const subAr = arr.slice(0, arr.length - 1); + console.log('log:', lastElem, ' :', subAr); + console.log('sorting subar'); + /* subAr.sort(this.compare);*/ + subAr.sort((a, b) => { + let result = 0; + + for (let i = 0; i < this.sortList.length; i++) { + const sortDetails = this.sortList[i]; + const isDesc = sortDetails.order.toLowerCase() === Const.SORT_DESC; + + const { sortFunc, sortFuncExtraData } = this.colInfos[sortDetails.sortField]; + if (sortFunc) { + result = sortFunc(a, b, sortDetails.order, sortDetails.sortField, sortFuncExtraData); } else { - if (typeof valueA === 'string') { - result = valueA.localeCompare(valueB); + const valueA = a[sortDetails.sortField] === null ? '' : a[sortDetails.sortField]; + const valueB = b[sortDetails.sortField] === null ? '' : b[sortDetails.sortField]; + if (isDesc) { + if (typeof valueB === 'string') { + result = valueB.localeCompare(valueA); + } else { + result = valueA > valueB ? -1 : ((valueA < valueB) ? 1 : 0); + } } else { - result = valueA < valueB ? -1 : ((valueA > valueB) ? 1 : 0); + if (typeof valueA === 'string') { + result = valueA.localeCompare(valueB); + } else { + result = valueA < valueB ? -1 : ((valueA > valueB) ? 1 : 0); + } } } + if (result !== 0) { + return result; + } } - if (result !== 0) { - return result; + return result; + }); + subAr.push(lastElem); + arr = subAr; + } else { + arr.sort((a, b) => { + let result = 0; + for (let i = 0; i < this.sortList.length; i++) { + const sortDetails = this.sortList[i]; + const isDesc = sortDetails.order.toLowerCase() === Const.SORT_DESC; + + const { sortFunc, sortFuncExtraData } = this.colInfos[sortDetails.sortField]; + if (sortFunc) { + result = sortFunc(a, b, sortDetails.order, sortDetails.sortField, sortFuncExtraData); + } else { + const valueA = a[sortDetails.sortField] === null ? '' : a[sortDetails.sortField]; + const valueB = b[sortDetails.sortField] === null ? '' : b[sortDetails.sortField]; + if (isDesc) { + if (typeof valueB === 'string') { + result = valueB.localeCompare(valueA); + } else { + result = valueA > valueB ? -1 : ((valueA < valueB) ? 1 : 0); + } + } else { + if (typeof valueA === 'string') { + result = valueA.localeCompare(valueB); + } else { + result = valueA < valueB ? -1 : ((valueA > valueB) ? 1 : 0); + } + } + } + if (result !== 0) { + return result; + } } - } - - return result; - }); - + return result; + }); + } return arr; }