diff --git a/docs/columns.md b/docs/columns.md
index afeffe7..5bb23a6 100644
--- a/docs/columns.md
+++ b/docs/columns.md
@@ -13,6 +13,7 @@ Available properties in a column object:
* [formatExtraData](#formatExtraData)
* [sort](#sort)
* [sortFunc](#sortFunc)
+* [sortCaret](#sortCaret)
* [onSort](#onSort)
* [classes](#classes)
* [style](#style)
@@ -154,6 +155,20 @@ Enable the column sort via a `true` value given.
}
```
+## column.sortCaret - [Function]
+Use`column.sortCaret` to custom the sort caret. This callback function accept two arguments: `order` and `column`
+
+```js
+{
+ // omit...
+ sort: true,
+ sortCaret: (order, column) => {
+ return //...
+ }
+}
+```
+> The possible value of `order` argument is **`asc`**, **`desc`** and **`undefined`**.
+
## column.classes - [String | Function]
It's available to have custom class on table column:
diff --git a/packages/react-bootstrap-table2-example/examples/basic/exposed-function.js b/packages/react-bootstrap-table2-example/examples/basic/exposed-function.js
new file mode 100644
index 0000000..6ea656d
--- /dev/null
+++ b/packages/react-bootstrap-table2-example/examples/basic/exposed-function.js
@@ -0,0 +1,182 @@
+/* eslint no-return-assign: 0 */
+/* eslint no-console: 0 */
+import React from 'react';
+
+import BootstrapTable from 'react-bootstrap-table-next';
+import paginationFactory from 'react-bootstrap-table2-paginator';
+import filterFactory, { textFilter } from 'react-bootstrap-table2-filter';
+import Code from 'components/common/code-block';
+import { productsGenerator } from 'utils/common';
+
+const products = productsGenerator(63);
+
+const columns = [{
+ dataField: 'id',
+ text: 'Product ID',
+ sort: true
+}, {
+ dataField: 'name',
+ text: 'Product Name',
+ sort: true,
+ filter: textFilter()
+}, {
+ dataField: 'price',
+ text: 'Product Price',
+ sort: true,
+ filter: textFilter()
+}];
+
+const sourceCode = `\
+import BootstrapTable from 'react-bootstrap-table-next';
+
+const columns = [{
+ dataField: 'id',
+ text: 'Product ID'
+}, {
+ dataField: 'name',
+ text: 'Product Name'
+}, {
+ dataField: 'price',
+ text: 'Product Price'
+}];
+
+class ExposedFunctionTable extends React.Component {
+ handleGetCurrentData = () => {
+ console.log(this.node.table.props.data);
+ }
+
+ handleGetSelectedData = () => {
+ console.log(this.node.selectionContext.state.selected);
+ }
+
+ handleGetExpandedData = () => {
+ console.log(this.node.rowExpandContext.state.expanded);
+ }
+
+ handleGetCurrentPage = () => {
+ console.log(this.node.paginationContext.currPage);
+ }
+
+ handleGetCurrentSizePerPage = () => {
+ console.log(this.node.paginationContext.currSizePerPage);
+ }
+
+ handleGetCurrentSortColumn = () => {
+ console.log(this.node.sortContext.state.sortColumn);
+ }
+
+ handleGetCurrentSortOrder = () => {
+ console.log(this.node.sortContext.state.sortOrder);
+ }
+
+ handleGetCurrentFilter = () => {
+ console.log(this.node.filterContext.currFilters);
+ }
+
+ render() {
+ const expandRow = {
+ renderer: row => (
+
+
.....
+
You can render anything here, also you can add additional data on every row object
+
expandRow.renderer callback will pass the origin row object to you
+
+ ),
+ showExpandColumn: true
+ };
+ return (
+
+
+
+
+
+
+
+
+
+ this.node = n }
+ keyField="id"
+ data={ products }
+ columns={ columns }
+ filter={ filterFactory() }
+ pagination={ paginationFactory() }
+ selectRow={ { mode: 'checkbox', clickToSelect: true } }
+ expandRow={ expandRow }
+ />
+ { sourceCode }
+
+ );
+ }
+}
+`;
+
+export default class ExposedFunctionTable extends React.Component {
+ handleGetCurrentData = () => {
+ console.log(this.node.table.props.data);
+ }
+
+ handleGetSelectedData = () => {
+ console.log(this.node.selectionContext.state.selected);
+ }
+
+ handleGetExpandedData = () => {
+ console.log(this.node.rowExpandContext.state.expanded);
+ }
+
+ handleGetCurrentPage = () => {
+ console.log(this.node.paginationContext.currPage);
+ }
+
+ handleGetCurrentSizePerPage = () => {
+ console.log(this.node.paginationContext.currSizePerPage);
+ }
+
+ handleGetCurrentSortColumn = () => {
+ console.log(this.node.sortContext.state.sortColumn);
+ }
+
+ handleGetCurrentSortOrder = () => {
+ console.log(this.node.sortContext.state.sortOrder);
+ }
+
+ handleGetCurrentFilter = () => {
+ console.log(this.node.filterContext.currFilters);
+ }
+
+ render() {
+ const expandRow = {
+ renderer: row => (
+
+
{ `This Expand row is belong to rowKey ${row.id}` }
+
You can render anything here, also you can add additional data on every row object
+
expandRow.renderer callback will pass the origin row object to you
+
+ ),
+ showExpandColumn: true
+ };
+ return (
+
+
+
+
+
+
+
+
+
+ this.node = n }
+ keyField="id"
+ data={ products }
+ columns={ columns }
+ filter={ filterFactory() }
+ pagination={ paginationFactory() }
+ selectRow={ { mode: 'checkbox', clickToSelect: true } }
+ expandRow={ expandRow }
+ />
+ { sourceCode }
+
+ );
+ }
+}
diff --git a/packages/react-bootstrap-table2-example/examples/sort/custom-sort-caret.js b/packages/react-bootstrap-table2-example/examples/sort/custom-sort-caret.js
new file mode 100644
index 0000000..4a1a650
--- /dev/null
+++ b/packages/react-bootstrap-table2-example/examples/sort/custom-sort-caret.js
@@ -0,0 +1,59 @@
+/* eslint no-unused-vars: 0 */
+import React from 'react';
+
+import BootstrapTable from 'react-bootstrap-table-next';
+import Code from 'components/common/code-block';
+import { productsGenerator } from 'utils/common';
+
+const products = productsGenerator();
+
+const columns = [{
+ dataField: 'id',
+ text: 'Product ID',
+ sort: true
+}, {
+ dataField: 'name',
+ text: 'Product Name',
+ sort: true,
+ sortCaret: (order, column) => {
+ if (!order) return ( Desc/Asc);
+ else if (order === 'asc') return ( Desc/Asc);
+ else if (order === 'desc') return ( Desc/Asc);
+ return null;
+ }
+}, {
+ dataField: 'price',
+ text: 'Product Price'
+}];
+
+const sourceCode = `\
+import BootstrapTable from 'react-bootstrap-table-next';
+
+const columns = [{
+ dataField: 'id',
+ text: 'Product ID',
+ sort: true
+}, {
+ dataField: 'name',
+ text: 'Product Name',
+ sort: true,
+ sortCaret: (order, column) => {
+ if (!order) return ( Desc/Asc);
+ else if (order === 'asc') return ( Desc/Asc);
+ else if (order === 'desc') return ( Desc/Asc);
+ return null;
+ }
+}, {
+ dataField: 'price',
+ text: 'Product Price'
+}];
+
+
+`;
+
+export default () => (
+
+
+ { sourceCode }
+
+);
diff --git a/packages/react-bootstrap-table2-example/stories/index.js b/packages/react-bootstrap-table2-example/stories/index.js
index 771655f..2941f37 100644
--- a/packages/react-bootstrap-table2-example/stories/index.js
+++ b/packages/react-bootstrap-table2-example/stories/index.js
@@ -13,6 +13,7 @@ import NoDataTable from 'examples/basic/no-data-table';
import CustomizedIdClassesTable from 'examples/basic/customized-id-classes';
import CaptionTable from 'examples/basic/caption-table';
import LargeTable from 'examples/basic/large-table';
+import ExposedAPITable from 'examples/basic/exposed-function';
// bootstrap 4
import Bootstrap4DefaultSortTable from 'examples/bootstrap4/sort';
@@ -83,6 +84,7 @@ import DefaultSortTable from 'examples/sort/default-sort-table';
import DefaultSortDirectionTable from 'examples/sort/default-sort-direction';
import SortEvents from 'examples/sort/sort-events';
import CustomSortTable from 'examples/sort/custom-sort-table';
+import CustomSortCaretTable from 'examples/sort/custom-sort-caret';
import HeaderSortingClassesTable from 'examples/sort/header-sorting-classes';
import HeaderSortingStyleTable from 'examples/sort/header-sorting-style';
@@ -189,7 +191,8 @@ storiesOf('Basic Table', module)
.add('Indication For Empty Table', () => )
.add('Customized id and class table', () => )
.add('Table with caption', () => )
- .add('Large Table', () => );
+ .add('Large Table', () => )
+ .add('Exposed API', () => );
storiesOf('Bootstrap 4', module)
.addDecorator(bootstrapStyle(BOOTSTRAP_VERSION.FOUR))
@@ -267,6 +270,7 @@ storiesOf('Sort Table', module)
.add('Default Sort Direction Table', () => )
.add('Sort Events', () => )
.add('Custom Sort Fuction', () => )
+ .add('Custom Sort Caret', () => )
.add('Custom Classes on Sorting Header Column', () => )
.add('Custom Style on Sorting Header Column', () => );
diff --git a/packages/react-bootstrap-table2-paginator/src/context.js b/packages/react-bootstrap-table2-paginator/src/context.js
index eb58ceb..d5ffb96 100644
--- a/packages/react-bootstrap-table2-paginator/src/context.js
+++ b/packages/react-bootstrap-table2-paginator/src/context.js
@@ -68,6 +68,9 @@ export default (
currPage = newPage;
needNewState = true;
}
+ } else {
+ this.currPage = nextProps.pagination.options.page;
+ this.currSizePerPage = nextProps.pagination.options.sizePerPage;
}
if (needNewState) {
diff --git a/packages/react-bootstrap-table2-paginator/test/context.test.js b/packages/react-bootstrap-table2-paginator/test/context.test.js
index 9d13658..d72caea 100644
--- a/packages/react-bootstrap-table2-paginator/test/context.test.js
+++ b/packages/react-bootstrap-table2-paginator/test/context.test.js
@@ -160,6 +160,27 @@ describe('PaginationContext', () => {
});
});
+ describe('when remote pagination is enable', () => {
+ beforeEach(() => {
+ wrapper = shallow(shallowContext({ ...defaultPagination }, true));
+ instance = wrapper.instance();
+ wrapper.render();
+ nextProps = {
+ data,
+ pagination: { ...defaultPagination, options: { page: 3, sizePerPage: 5 } }
+ };
+ instance.componentWillReceiveProps(nextProps);
+ });
+
+ it('should always set currPage from nextProps.pagination.options.page', () => {
+ expect(instance.currPage).toEqual(nextProps.pagination.options.page);
+ });
+
+ it('should always set currSizePerPage from nextProps.pagination.options.sizePerPage', () => {
+ expect(instance.currSizePerPage).toEqual(nextProps.pagination.options.sizePerPage);
+ });
+ });
+
describe('when page is not align', () => {
beforeEach(() => {
wrapper = shallow(shallowContext({
diff --git a/packages/react-bootstrap-table2-toolkit/src/search/context.js b/packages/react-bootstrap-table2-toolkit/src/search/context.js
index c579999..90484bf 100644
--- a/packages/react-bootstrap-table2-toolkit/src/search/context.js
+++ b/packages/react-bootstrap-table2-toolkit/src/search/context.js
@@ -39,8 +39,10 @@ export default (options = {
const { data, columns } = this.props;
let { searchText } = this.props;
- if (isRemoteSearch() && this.performRemoteSearch) {
- handleRemoteSearchChange(searchText);
+ if (isRemoteSearch()) {
+ if (this.performRemoteSearch) {
+ handleRemoteSearchChange(searchText);
+ }
return data;
}
diff --git a/packages/react-bootstrap-table2/src/contexts/index.js b/packages/react-bootstrap-table2/src/contexts/index.js
index 60c3a55..72436ce 100644
--- a/packages/react-bootstrap-table2/src/contexts/index.js
+++ b/packages/react-bootstrap-table2/src/contexts/index.js
@@ -66,6 +66,7 @@ const withContext = Base =>
selectionProps
) => (
this.table = n }
{ ...this.props }
{ ...selectionProps }
{ ...sortProps }
@@ -91,6 +92,7 @@ const withContext = Base =>
) => (
this.selectionContext = n }
selectRow={ this.props.selectRow }
data={ rootProps.getData(filterProps, searchProps, sortProps, paginationProps) }
>
@@ -123,6 +125,7 @@ const withContext = Base =>
) => (
this.rowExpandContext = n }
expandRow={ this.props.expandRow }
data={ rootProps.getData(filterProps, searchProps, sortProps, paginationProps) }
>
diff --git a/packages/react-bootstrap-table2/src/header-cell.js b/packages/react-bootstrap-table2/src/header-cell.js
index 79b4b9b..1270082 100644
--- a/packages/react-bootstrap-table2/src/header-cell.js
+++ b/packages/react-bootstrap-table2/src/header-cell.js
@@ -24,6 +24,7 @@ const HeaderCell = (props) => {
const {
text,
sort,
+ sortCaret,
filter,
filterRenderer,
headerTitle,
@@ -69,7 +70,7 @@ const HeaderCell = (props) => {
cellAttrs.className = cs(cellAttrs.className, 'sortable');
if (sorting) {
- sortSymbol = ;
+ sortSymbol = sortCaret ? sortCaret(sortOrder, column) : ;
// append customized classes or style if table was sorting based on the current column.
cellClasses = cs(
@@ -86,7 +87,7 @@ const HeaderCell = (props) => {
: headerSortingStyle
};
} else {
- sortSymbol = ;
+ sortSymbol = sortCaret ? sortCaret(undefined, column) : ;
}
}
@@ -151,6 +152,7 @@ HeaderCell.propTypes = {
onSort: PropTypes.func,
sorting: PropTypes.bool,
sortOrder: PropTypes.oneOf([Const.SORT_ASC, Const.SORT_DESC]),
+ sortCaret: PropTypes.func,
isLastSorting: PropTypes.bool,
onFilter: PropTypes.func,
onExternalFilter: PropTypes.func
diff --git a/packages/react-bootstrap-table2/test/header-cell.test.js b/packages/react-bootstrap-table2/test/header-cell.test.js
index 6814135..b0c4525 100644
--- a/packages/react-bootstrap-table2/test/header-cell.test.js
+++ b/packages/react-bootstrap-table2/test/header-cell.test.js
@@ -403,6 +403,24 @@ describe('HeaderCell', () => {
it('header should render SortSymbol as default', () => {
expect(wrapper.find(SortSymbol).length).toBe(1);
});
+
+ describe('when sortCaret is defined ', () => {
+ beforeEach(() => {
+ column = { ...column, sortCaret: jest.fn() };
+ wrapper = shallow(
+
+ );
+ });
+
+ it('header should not render SortSymbol', () => {
+ expect(wrapper.find(SortSymbol).length).toBe(0);
+ });
+
+ it('should call column.sortCaret correctly', () => {
+ expect(column.sortCaret).toHaveBeenCalledTimes(1);
+ expect(column.sortCaret).toHaveBeenCalledWith(undefined, column);
+ });
+ });
});
describe('and sorting prop is true', () => {
@@ -420,6 +438,30 @@ describe('HeaderCell', () => {
});
});
+ describe('when sortCaret is defined ', () => {
+ beforeEach(() => {
+ column = { ...column, sortCaret: jest.fn() };
+ wrapper = shallow(
+
+ );
+ });
+
+ it('header should not render SortSymbol', () => {
+ expect(wrapper.find(SortSymbol).length).toBe(0);
+ });
+
+ it('should call column.sortCaret correctly', () => {
+ expect(column.sortCaret).toHaveBeenCalledTimes(1);
+ expect(column.sortCaret).toHaveBeenCalledWith(Const.SORT_ASC, column);
+ });
+ });
+
describe('when headerSortingClasses is defined ', () => {
const classes = 'foo';
const order = Const.SORT_DESC;