From 316b4e53021d8060b98c9a06cb3ffb607c3ff254 Mon Sep 17 00:00:00 2001
From: Allen
Date: Mon, 30 Oct 2017 16:07:59 +0800
Subject: [PATCH] fix #133
* implement row events
* add story for row event
* add tests for row events
* patch docs for rowEvents
---
docs/README.md | 21 +++++--
.../examples/rows/row-event.js | 54 ++++++++++++++++++
.../stories/index.js | 4 +-
packages/react-bootstrap-table2/src/body.js | 5 +-
.../src/bootstrap-table.js | 5 +-
packages/react-bootstrap-table2/src/row.js | 46 +++++++++------
.../react-bootstrap-table2/test/body.test.js | 24 ++++++++
.../react-bootstrap-table2/test/row.test.js | 57 ++++++++++++++++++-
8 files changed, 191 insertions(+), 25 deletions(-)
create mode 100644 packages/react-bootstrap-table2-example/examples/rows/row-event.js
diff --git a/docs/README.md b/docs/README.md
index aab6265..fb53620 100644
--- a/docs/README.md
+++ b/docs/README.md
@@ -17,6 +17,7 @@
* [selectRow](#selectRow)
* [rowStyle](#rowStyle)
* [rowClasses](#rowClasses)
+* [rowEvents](#rowEvents)
* [defaultSorted](#defaultSorted)
### keyField(**required**) - [String]
@@ -50,7 +51,7 @@ Makes table rows selectable, please see [selectRow definition](./row-selection.m
Custom the style of table rows:
```js
-
+
```
This prop also accept a callback function for flexible to custom row style:
@@ -60,14 +61,14 @@ const rowStyle = (row, rowIndex) => {
return { ... };
};
-
+
```
### rowClasses = [String | Function]
Custom the style of table rows:
```js
-
+
```
This prop also accept a callback function for flexible to custom row style:
@@ -77,7 +78,19 @@ const rowClasses = (row, rowIndex) => {
return 'custom-row-class';
};
-
+
+```
+
+### rowEvents - [Object]
+Custom the events on row:
+
+```js
+const rowEvents = {
+ onClick: (e) => {
+ ....
+ }
+};
+
```
### defaultSorted - [Array]
diff --git a/packages/react-bootstrap-table2-example/examples/rows/row-event.js b/packages/react-bootstrap-table2-example/examples/rows/row-event.js
new file mode 100644
index 0000000..1ec5022
--- /dev/null
+++ b/packages/react-bootstrap-table2-example/examples/rows/row-event.js
@@ -0,0 +1,54 @@
+/* eslint no-unused-vars: 0 */
+/* eslint no-console: 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 columns = [{
+ dataField: 'id',
+ text: 'Product ID'
+}, {
+ dataField: 'name',
+ text: 'Product Name'
+}, {
+ dataField: 'price',
+ text: 'Product Price'
+}];
+
+const rowEvents = {
+ onClick: (e) => {
+ console.log('click on row');
+ }
+};
+
+const sourceCode = `\
+const columns = [{
+ dataField: 'id',
+ text: 'Product ID'
+}, {
+ dataField: 'name',
+ text: 'Product Name'
+}, {
+ dataField: 'price',
+ text: 'Product Price'
+}];
+
+const rowEvents = {
+ onClick: (e) => {
+ console.log('click on row');
+ }
+};
+
+
+`;
+
+export default () => (
+
+
+ { sourceCode }
+
+);
diff --git a/packages/react-bootstrap-table2-example/stories/index.js b/packages/react-bootstrap-table2-example/stories/index.js
index c267778..c97b373 100644
--- a/packages/react-bootstrap-table2-example/stories/index.js
+++ b/packages/react-bootstrap-table2-example/stories/index.js
@@ -35,6 +35,7 @@ import HeaderColumnAttrsTable from 'examples/header-columns/column-attrs-table';
// work on rows
import RowStyleTable from 'examples/rows/row-style';
import RowClassTable from 'examples/rows/row-class';
+import RowEventTable from 'examples/rows/row-event';
// table sort
import EnableSortTable from 'examples/sort/enable-sort-table';
@@ -109,7 +110,8 @@ storiesOf('Work on Header Columns', module)
storiesOf('Work on Rows', module)
.add('Customize Row Style', () => )
- .add('Customize Row Class', () => );
+ .add('Customize Row Class', () => )
+ .add('Row Event', () => );
storiesOf('Sort Table', module)
.add('Enable Sort', () => )
diff --git a/packages/react-bootstrap-table2/src/body.js b/packages/react-bootstrap-table2/src/body.js
index 85f4e35..b0182da 100644
--- a/packages/react-bootstrap-table2/src/body.js
+++ b/packages/react-bootstrap-table2/src/body.js
@@ -22,7 +22,8 @@ const Body = (props) => {
selectRow,
selectedRowKeys,
rowStyle,
- rowClasses
+ rowClasses,
+ rowEvents
} = props;
const {
@@ -45,6 +46,7 @@ const Body = (props) => {
? selectedRowKeys.includes(key)
: null;
+ const attrs = rowEvents || {};
let style = _.isFunction(rowStyle) ? rowStyle(row, index) : rowStyle;
let classes = (_.isFunction(rowClasses) ? rowClasses(row, index) : rowClasses);
if (selected) {
@@ -84,6 +86,7 @@ const Body = (props) => {
selectRow={ selectRow }
style={ style }
className={ classes }
+ attrs={ attrs }
/>
);
});
diff --git a/packages/react-bootstrap-table2/src/bootstrap-table.js b/packages/react-bootstrap-table2/src/bootstrap-table.js
index b82d819..d77d47f 100644
--- a/packages/react-bootstrap-table2/src/bootstrap-table.js
+++ b/packages/react-bootstrap-table2/src/bootstrap-table.js
@@ -37,7 +37,8 @@ class BootstrapTable extends PropsBaseResolver(Component) {
noDataIndication,
caption,
rowStyle,
- rowClasses
+ rowClasses,
+ rowEvents
} = this.props;
const tableClass = cs('table', {
@@ -87,6 +88,7 @@ class BootstrapTable extends PropsBaseResolver(Component) {
selectedRowKeys={ store.getSelectedRowKeys() }
rowStyle={ rowStyle }
rowClasses={ rowClasses }
+ rowEvents={ rowEvents }
/>
@@ -145,6 +147,7 @@ BootstrapTable.propTypes = {
onRowSelect: PropTypes.func,
onAllRowsSelect: PropTypes.func,
rowStyle: PropTypes.oneOfType([PropTypes.object, PropTypes.func]),
+ rowEvents: PropTypes.object,
rowClasses: PropTypes.oneOfType([PropTypes.string, PropTypes.func]),
defaultSorted: PropTypes.arrayOf(PropTypes.shape({
dataField: PropTypes.string.isRequired,
diff --git a/packages/react-bootstrap-table2/src/row.js b/packages/react-bootstrap-table2/src/row.js
index d08fbec..a39d965 100644
--- a/packages/react-bootstrap-table2/src/row.js
+++ b/packages/react-bootstrap-table2/src/row.js
@@ -15,7 +15,7 @@ class Row extends Component {
this.handleRowClick = this.handleRowClick.bind(this);
}
- handleRowClick() {
+ handleRowClick(e) {
const {
row,
selected,
@@ -25,22 +25,31 @@ class Row extends Component {
selectRow: {
onRowSelect,
clickToEdit
- }
+ },
+ cellEdit: { mode },
+ attrs
} = this.props;
- const key = _.get(row, keyField);
- if (selectable) {
- const { cellEdit: { mode } } = this.props;
- if (mode === Const.DBCLICK_TO_CELL_EDIT && clickToEdit) {
- this.clickNum += 1;
- _.debounce(() => {
- if (this.clickNum === 1) {
- onRowSelect(key, !selected, rowIndex);
- }
- this.clickNum = 0;
- }, Const.DELAY_FOR_DBCLICK)();
- } else {
+
+ const clickFn = () => {
+ if (attrs.onClick) {
+ attrs.onClick(e);
+ }
+ if (selectable) {
+ const key = _.get(row, keyField);
onRowSelect(key, !selected, rowIndex);
}
+ };
+
+ if (mode === Const.DBCLICK_TO_CELL_EDIT && clickToEdit) {
+ this.clickNum += 1;
+ _.debounce(() => {
+ if (this.clickNum === 1) {
+ clickFn();
+ }
+ this.clickNum = 0;
+ }, Const.DELAY_FOR_DBCLICK)();
+ } else {
+ clickFn();
}
}
@@ -52,6 +61,7 @@ class Row extends Component {
rowIndex,
className,
style,
+ attrs,
cellEdit,
selected,
selectRow,
@@ -70,7 +80,7 @@ class Row extends Component {
const key = _.get(row, keyField);
const { clickToSelect, hideSelectColumn } = selectRow;
- const trAttrs = {};
+ const trAttrs = { ...attrs };
if (clickToSelect) {
trAttrs.onClick = this.handleRowClick;
}
@@ -143,13 +153,15 @@ Row.propTypes = {
rowIndex: PropTypes.number.isRequired,
columns: PropTypes.array.isRequired,
style: PropTypes.object,
- className: PropTypes.string
+ className: PropTypes.string,
+ attrs: PropTypes.object
};
Row.defaultProps = {
editable: true,
style: {},
- className: null
+ className: null,
+ attrs: {}
};
export default Row;
diff --git a/packages/react-bootstrap-table2/test/body.test.js b/packages/react-bootstrap-table2/test/body.test.js
index 51176d6..5674b83 100644
--- a/packages/react-bootstrap-table2/test/body.test.js
+++ b/packages/react-bootstrap-table2/test/body.test.js
@@ -339,6 +339,30 @@ describe('Body', () => {
});
});
+ describe('when rowEvents prop is defined', () => {
+ const rowEvents = { onClick: sinon.stub() };
+
+ describe('and it is a string', () => {
+ beforeEach(() => {
+ wrapper = shallow(
+ );
+ });
+
+ it('should rendering Row component with correct attrs prop', () => {
+ const rows = wrapper.find(Row);
+ rows.forEach((row) => {
+ expect(row.props().attrs).toEqual(rowEvents);
+ });
+ });
+ });
+ });
+
describe('when cellEdit.nonEditableRows props is defined', () => {
const nonEditableRows = [data[1].id];
const cellEdit = {
diff --git a/packages/react-bootstrap-table2/test/row.test.js b/packages/react-bootstrap-table2/test/row.test.js
index 10555bc..de8f5c5 100644
--- a/packages/react-bootstrap-table2/test/row.test.js
+++ b/packages/react-bootstrap-table2/test/row.test.js
@@ -84,7 +84,7 @@ describe('Row', () => {
/>);
});
- it('should render component with style successfully', () => {
+ it('should render component with className successfully', () => {
expect(wrapper.length).toBe(1);
expect(wrapper.hasClass(className)).toBe(true);
});
@@ -442,6 +442,27 @@ describe('Row', () => {
});
});
+ describe('when attrs prop is defined', () => {
+ const customClickCallBack = sinon.stub();
+ const attrs = { 'data-index': 1, onClick: customClickCallBack };
+ beforeEach(() => {
+ wrapper = shallow(
+
);
+ });
+
+ it('should render component with correct attributes', () => {
+ expect(wrapper.length).toBe(1);
+ expect(wrapper.prop('data-index')).toBe(attrs['data-index']);
+ expect(wrapper.prop('onClick')).toBeDefined();
+ });
+ });
+
describe('when selectRow.mode is ROW_SELECT_DISABLED (row was un-selectable)', () => {
beforeEach(() => {
wrapper = shallow(
@@ -697,5 +718,39 @@ describe('Row', () => {
expect(wrapper.instance().clickNum).toEqual(2);
});
});
+
+ describe('when attrs.onClick prop is defined', () => {
+ const customClickCallBack = sinon.stub();
+ const attrs = { onClick: customClickCallBack };
+
+ beforeEach(() => {
+ onRowSelectCallBack = sinon.stub();
+ selectRow = {
+ mode: 'checkbox',
+ clickToSelect: true,
+ onRowSelect: onRowSelectCallBack
+ };
+ wrapper = shallow(
+
);
+ wrapper.find('tr').simulate('click');
+ });
+
+ it('should calling attrs.onClick callback', () => {
+ expect(customClickCallBack.callCount).toEqual(1);
+ });
+
+ it('should calling selectRow.onRowSelect callback', () => {
+ expect(onRowSelectCallBack.callCount).toEqual(1);
+ });
+ });
});
});