diff --git a/docs/columns.md b/docs/columns.md
index 9fe7745a3..52aaa1749 100644
--- a/docs/columns.md
+++ b/docs/columns.md
@@ -25,6 +25,8 @@ Available properties in a column object:
* [headerEvents](#headerEvents)
* [headerAlign](#headerAlign)
* [headerAttrs](#headerAttrs)
+* [headerSortingClasses](#headerSortingClasses)
+* [headerSortingStyle](#headerSortingStyle)
* [editable](#editable)
* [validator](#validator)
* [editCellStyle](#editCellStyle)
@@ -419,6 +421,35 @@ A new `Object` will be the result of element headerAttrs.
> Same as [column.attrs](#attrs), it has lower priority and will be
> overwrited when other props related to HTML attributes were given.
+### headerSortingClasses - [String | Function]
+
+`headerSortingClasses` allows to customize `class` for header cell when this column is sorting.
+
+```js
+const headerSortingClasses = 'demo-sorting';
+```
+
+Furthermore, it also accepts a callback which takes **4** arguments and `String` is expected to return:
+
+```js
+const headerSortingClasses = (column, sortOrder, isLastSorting, colIndex) => { ... }
+```
+
+* `column`: The value of current column.
+* `sortOrder`: The order of current sorting
+* `isLastSorting`: Is the last one of sorted columns.
+* `colIndex`: The index of the current column being processed in BootstrapTable.
+
+### headerSortingStyle - [Object | Function]
+
+It's similiar to [headerSortingClasses](#headerSortingClasses). It allows to customize the style of header cell when this column is sorting. A style `Object` and `callback` are acceptable. `callback` takes **4** arguments and an `Object` is expected to return:
+
+```js
+const sortingHeaderStyle = {
+ backgroundColor: 'red'
+};
+```
+
## column.editable - [Bool | Function]
`column.editable` default is true, means every column is editable if you configure [`cellEdit`](./README.md#cellEdit). But you can disable some columns editable via setting `false`.
diff --git a/packages/react-bootstrap-table2-example/examples/sort/default-sort-table.js b/packages/react-bootstrap-table2-example/examples/sort/default-sort-table.js
index 0f238a849..9cda0a41e 100644
--- a/packages/react-bootstrap-table2-example/examples/sort/default-sort-table.js
+++ b/packages/react-bootstrap-table2-example/examples/sort/default-sort-table.js
@@ -41,7 +41,17 @@ const columns = [{
sort: true
}];
-
+const defaultSorted = [{
+ dataField: 'name',
+ order: 'desc'
+}];
+
+
`;
diff --git a/packages/react-bootstrap-table2-example/examples/sort/header-sorting-classes.js b/packages/react-bootstrap-table2-example/examples/sort/header-sorting-classes.js
new file mode 100644
index 000000000..d70bdd752
--- /dev/null
+++ b/packages/react-bootstrap-table2-example/examples/sort/header-sorting-classes.js
@@ -0,0 +1,61 @@
+/* eslint
+ no-unused-vars: 0
+ arrow-body-style: 0
+*/
+
+import React from 'react';
+
+import BootstrapTable from 'react-bootstrap-table2';
+import Code from 'components/common/code-block';
+import { productsGenerator } from 'utils/common';
+
+const products = productsGenerator();
+
+const headerSortingClasses = (column, sortOrder, isLastSorting, colIndex) => (
+ sortOrder === 'asc' ? 'demo-sorting-asc' : 'demo-sorting-desc'
+);
+
+const columns = [{
+ dataField: 'id',
+ text: 'Product ID',
+ sort: true,
+ headerSortingClasses
+}, {
+ dataField: 'name',
+ text: 'Product Name',
+ sort: true,
+ headerSortingClasses
+}, {
+ dataField: 'price',
+ text: 'Product Price'
+}];
+
+const sourceCode = `\
+const headerSortingClasses = (column, sortOrder, isLastSorting, colIndex) => (
+ sortOrder === 'asc' ? 'demo-sorting-asc' : 'demo-sorting-desc'
+);
+
+const columns = [{
+ dataField: 'id',
+ text: 'Product ID',
+ sort: true,
+ headerSortingClasses
+}, {
+ dataField: 'name',
+ text: 'Product Name',
+ sort: true,
+ headerSortingClasses
+}, {
+ dataField: 'price',
+ text: 'Product Price'
+}];
+
+
+`;
+
+export default () => (
+
+
+ { sourceCode }
+
+);
diff --git a/packages/react-bootstrap-table2-example/examples/sort/header-sorting-style.js b/packages/react-bootstrap-table2-example/examples/sort/header-sorting-style.js
new file mode 100644
index 000000000..c39096542
--- /dev/null
+++ b/packages/react-bootstrap-table2-example/examples/sort/header-sorting-style.js
@@ -0,0 +1,54 @@
+/* eslint no-unused-vars: 0 */
+import React from 'react';
+
+import BootstrapTable from 'react-bootstrap-table2';
+import Code from 'components/common/code-block';
+import { productsGenerator } from 'utils/common';
+
+const products = productsGenerator();
+
+const headerSortingStyle = { backgroundColor: '#c8e6c9' };
+
+const columns = [{
+ dataField: 'id',
+ text: 'Product ID',
+ sort: true,
+ headerSortingStyle
+}, {
+ dataField: 'name',
+ text: 'Product Name',
+ sort: true,
+ headerSortingStyle
+}, {
+ dataField: 'price',
+ text: 'Product Price'
+}];
+
+
+const sourceCode = `\
+const headerSortingStyle = { backgroundColor: '#c8e6c9' };
+
+const columns = [{
+ dataField: 'id',
+ text: 'Product ID',
+ sort: true,
+ headerSortingStyle
+}, {
+ dataField: 'name',
+ text: 'Product Name',
+ sort: true,
+ headerSortingStyle
+}, {
+ 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 a99978238..738cfc63a 100644
--- a/packages/react-bootstrap-table2-example/stories/index.js
+++ b/packages/react-bootstrap-table2-example/stories/index.js
@@ -41,6 +41,8 @@ import RowEventTable from 'examples/rows/row-event';
import EnableSortTable from 'examples/sort/enable-sort-table';
import DefaultSortTable from 'examples/sort/default-sort-table';
import CustomSortTable from 'examples/sort/custom-sort-table';
+import HeaderSortingClassesTable from 'examples/sort/header-sorting-classes';
+import HeaderSortingStyleTable from 'examples/sort/header-sorting-style';
// cell editing
import ClickToEditTable from 'examples/cell-edit/click-to-edit-table';
@@ -127,7 +129,9 @@ storiesOf('Work on Rows', module)
storiesOf('Sort Table', module)
.add('Enable Sort', () => )
.add('Default Sort Table', () => )
- .add('Custom Sort Fuction', () => );
+ .add('Custom Sort Fuction', () => )
+ .add('Custom Classes on Sorting Header Column', () => )
+ .add('Custom Style on Sorting Header Column', () => );
storiesOf('Cell Editing', module)
.add('Click to Edit', () => )
diff --git a/packages/react-bootstrap-table2-example/stories/stylesheet/base/_base.scss b/packages/react-bootstrap-table2-example/stories/stylesheet/base/_base.scss
index 5097d01d6..5ee5a54bb 100644
--- a/packages/react-bootstrap-table2-example/stories/stylesheet/base/_base.scss
+++ b/packages/react-bootstrap-table2-example/stories/stylesheet/base/_base.scss
@@ -10,4 +10,5 @@ $grey-900: #212121;
$pink-500: #E91E63;
$green-lighten-2: #81c784;
$green-lighten-4: #c8e6c9;
+$light-blue: #00BFFF;
$markdown-color: #f6f8fa;
diff --git a/packages/react-bootstrap-table2-example/stories/stylesheet/sort/_index.scss b/packages/react-bootstrap-table2-example/stories/stylesheet/sort/_index.scss
new file mode 100644
index 000000000..bb8b1e889
--- /dev/null
+++ b/packages/react-bootstrap-table2-example/stories/stylesheet/sort/_index.scss
@@ -0,0 +1,8 @@
+.demo-sorting,
+.demo-sorting-asc {
+ background-color: $green-lighten-2;
+}
+
+.demo-sorting-desc {
+ background-color: $light-blue;
+}
diff --git a/packages/react-bootstrap-table2-example/stories/stylesheet/storybook.scss b/packages/react-bootstrap-table2-example/stories/stylesheet/storybook.scss
index 07510ceee..cf0a024e4 100644
--- a/packages/react-bootstrap-table2-example/stories/stylesheet/storybook.scss
+++ b/packages/react-bootstrap-table2-example/stories/stylesheet/storybook.scss
@@ -8,4 +8,5 @@
@import "cell-edit/index";
@import "row-selection/index";
@import "rows/index";
-@import "loading-overlay/index";
\ No newline at end of file
+@import "sort/index";
+@import "loading-overlay/index";
diff --git a/packages/react-bootstrap-table2/src/header-cell.js b/packages/react-bootstrap-table2/src/header-cell.js
index 15f7b529e..fb57adeb0 100644
--- a/packages/react-bootstrap-table2/src/header-cell.js
+++ b/packages/react-bootstrap-table2/src/header-cell.js
@@ -15,8 +15,10 @@ const HeaderCell = (props) => {
index,
onSort,
sorting,
- sortOrder
+ sortOrder,
+ isLastSorting
} = props;
+
const {
text,
sort,
@@ -27,7 +29,9 @@ const HeaderCell = (props) => {
headerEvents,
headerClasses,
headerStyle,
- headerAttrs
+ headerAttrs,
+ headerSortingClasses,
+ headerSortingStyle
} = column;
const cellAttrs = {
@@ -35,10 +39,10 @@ const HeaderCell = (props) => {
...headerEvents
};
const children = headerFormatter ? headerFormatter(column, index) : text;
- const cellClasses = _.isFunction(headerClasses) ? headerClasses(column, index) : headerClasses;
let cellStyle = {};
let sortSymbol;
+ let cellClasses = _.isFunction(headerClasses) ? headerClasses(column, index) : headerClasses;
if (headerStyle) {
cellStyle = _.isFunction(headerStyle) ? headerStyle(column, index) : headerStyle;
@@ -56,10 +60,6 @@ const HeaderCell = (props) => {
cellStyle.display = 'none';
}
- if (cellClasses) cellAttrs.className = cellClasses;
-
- if (!_.isEmptyObject(cellStyle)) cellAttrs.style = cellStyle;
-
if (sort) {
const customClick = cellAttrs.onClick;
cellAttrs.onClick = (e) => {
@@ -70,11 +70,30 @@ const HeaderCell = (props) => {
if (sorting) {
sortSymbol = ;
+
+ // append customized classes or style if table was sorting based on the current column.
+ cellClasses = cs(
+ cellClasses,
+ _.isFunction(headerSortingClasses)
+ ? headerSortingClasses(column, sortOrder, isLastSorting, index)
+ : headerSortingClasses
+ );
+
+ cellStyle = {
+ ...cellStyle,
+ ..._.isFunction(headerSortingStyle)
+ ? headerSortingStyle(column, sortOrder, isLastSorting, index)
+ : headerSortingStyle
+ };
} else {
sortSymbol = ;
}
}
+ if (cellClasses) cellAttrs.className = cs(cellAttrs.className, cellClasses);
+
+ if (!_.isEmptyObject(cellStyle)) cellAttrs.style = cellStyle;
+
return (
{ children }{ sortSymbol }
@@ -112,7 +131,8 @@ HeaderCell.propTypes = {
index: PropTypes.number.isRequired,
onSort: PropTypes.func,
sorting: PropTypes.bool,
- sortOrder: PropTypes.oneOf([Const.SORT_ASC, Const.SORT_DESC])
+ sortOrder: PropTypes.oneOf([Const.SORT_ASC, Const.SORT_DESC]),
+ isLastSorting: PropTypes.bool
};
export default HeaderCell;
diff --git a/packages/react-bootstrap-table2/src/header.js b/packages/react-bootstrap-table2/src/header.js
index e301eb032..da77cb9c7 100644
--- a/packages/react-bootstrap-table2/src/header.js
+++ b/packages/react-bootstrap-table2/src/header.js
@@ -27,6 +27,8 @@ const Header = (props) => {
{
columns.map((column, i) => {
const currSort = column.dataField === sortField;
+ const isLastSorting = column.dataField === sortField;
+
return (
{
onSort={ onSort }
sorting={ currSort }
sortOrder={ sortOrder }
+ isLastSorting={ isLastSorting }
/>);
})
}
diff --git a/packages/react-bootstrap-table2/test/header-cell.test.js b/packages/react-bootstrap-table2/test/header-cell.test.js
index 4e2dda5ca..43ef4da01 100644
--- a/packages/react-bootstrap-table2/test/header-cell.test.js
+++ b/packages/react-bootstrap-table2/test/header-cell.test.js
@@ -436,6 +436,233 @@ describe('HeaderCell', () => {
});
});
});
+
+ describe('when headerSortingClasses is defined ', () => {
+ const classes = 'foo';
+ const order = Const.SORT_DESC;
+
+ describe('if headerSortingClasses is a string', () => {
+ beforeEach(() => {
+ column = { ...column, headerSortingClasses: classes };
+ wrapper = shallow(
+ );
+ });
+
+ it('should append classes correctly', () => {
+ expect(wrapper.length).toBe(1);
+ expect(wrapper.hasClass(classes)).toBe(true);
+ });
+
+ it('should have sortable class on header cell', () => {
+ expect(wrapper.hasClass('sortable')).toBe(true);
+ });
+ });
+
+ describe('if headerSortingClasses is a function', () => {
+ let classesCallBack;
+ let isLastSorting;
+
+ beforeEach(() => {
+ classesCallBack = sinon.stub()
+ .withArgs(column, order, isLastSorting, index)
+ .returns(classes);
+
+ column = { ...column, headerSortingClasses: classesCallBack };
+ wrapper = shallow(
+ );
+ });
+
+ it('should append classes correctly', () => {
+ expect(wrapper.length).toBe(1);
+ expect(wrapper.hasClass(classes)).toBe(true);
+ });
+
+ it('should have sortable class on header cell', () => {
+ expect(wrapper.hasClass('sortable')).toBe(true);
+ });
+
+ it('should call custom class function with correct params', () => {
+ expect(classesCallBack.callCount).toBe(1);
+ expect(classesCallBack.calledWith(column, order, isLastSorting, index)).toBe(true);
+ });
+
+ describe('when the field is last sorting', () => {
+ it('should call custom classes function with isLastSorting being true', () => {
+ isLastSorting = true;
+ classesCallBack.reset();
+
+ wrapper = shallow(
+ );
+
+ expect(classesCallBack.callCount).toBe(1);
+ expect(classesCallBack.calledWith(column, order, isLastSorting, index)).toBe(true);
+ });
+ });
+ });
+
+ describe('if column.headerClasses is defined as well', () => {
+ it('should keep both classes', () => {
+ column = {
+ ...column,
+ headerClasses: 'td-test-class',
+ headerSortingClasses: classes
+ };
+
+ wrapper = shallow(
+
+ );
+
+ expect(wrapper.length).toBe(1);
+ expect(wrapper.hasClass('sortable')).toBe(true);
+ expect(wrapper.hasClass(classes)).toBe(true);
+ expect(wrapper.hasClass(column.headerClasses)).toBe(true);
+ });
+ });
+ });
+
+ describe('when headerSortingStyle is defined', () => {
+ const style = { backgroundColor: 'red' };
+ const order = Const.SORT_DESC;
+
+ describe('if headerSortingStyle is an object', () => {
+ beforeEach(() => {
+ column = { ...column, headerSortingStyle: style };
+
+ wrapper = shallow(
+
+ );
+ });
+
+ it('should append style correctly', () => {
+ expect(wrapper.length).toBe(1);
+ expect(wrapper.find('th').prop('style')).toEqual(style);
+ });
+ });
+
+ describe('if headerSortingStyle is a function', () => {
+ let styleCallBack;
+ let isLastSorting;
+
+ beforeEach(() => {
+ styleCallBack = sinon.stub()
+ .withArgs(column, order, isLastSorting, index)
+ .returns(style);
+
+ column = { ...column, headerSortingStyle: styleCallBack };
+
+ wrapper = shallow(
+ );
+ });
+
+ it('should append style correctly', () => {
+ expect(wrapper.length).toBe(1);
+ expect(wrapper.find('th').prop('style')).toEqual(style);
+ });
+
+ it('should call custom style function with correct params', () => {
+ expect(styleCallBack.callCount).toBe(1);
+ expect(styleCallBack.calledWith(column, order, isLastSorting, index)).toBe(true);
+ });
+
+ describe('when the field is last sorting', () => {
+ it('should call custom classes function with isLastSorting being true', () => {
+ isLastSorting = true;
+ styleCallBack.reset();
+
+ wrapper = shallow(
+ );
+
+ expect(styleCallBack.callCount).toBe(1);
+ expect(styleCallBack.calledWith(column, order, isLastSorting, index)).toBe(true);
+ });
+ });
+ });
+
+ describe('if column.headerStyle was defined as well', () => {
+ it('should keep both styles', () => {
+ column = {
+ ...column,
+ headerStyle: { opacity: '1' },
+ headerSortingStyle: style
+ };
+
+ wrapper = shallow(
+
+ );
+ expect(wrapper.length).toBe(1);
+ expect(wrapper.find('th').prop('style')).toEqual(expect.objectContaining({
+ ...style,
+ ...column.headerStyle
+ }));
+ });
+
+ it('headerSortingStyle should have higher priority', () => {
+ column = {
+ ...column,
+ headerStyle: { backgroundColor: 'green' },
+ headerSortingStyle: style
+ };
+
+ wrapper = shallow(
+
+ );
+ expect(wrapper.length).toBe(1);
+ expect(wrapper.find('th').prop('style')).toEqual(expect.objectContaining({
+ ...style
+ }));
+ expect(wrapper.find('th').prop('style')).not.toEqual(expect.objectContaining({
+ ...column.headerStyle
+ }));
+ });
+ });
+ });
});
describe('when column.headerEvents prop is defined and have custom onClick', () => {
|