mirror of
https://github.com/gosticks/react-bootstrap-table2.git
synced 2025-10-16 11:55:39 +00:00
fix #133
* implement row events * add story for row event * add tests for row events * patch docs for rowEvents
This commit is contained in:
parent
6110663075
commit
316b4e5302
@ -17,6 +17,7 @@
|
||||
* [selectRow](#selectRow)
|
||||
* [rowStyle](#rowStyle)
|
||||
* [rowClasses](#rowClasses)
|
||||
* [rowEvents](#rowEvents)
|
||||
* [defaultSorted](#defaultSorted)
|
||||
|
||||
### <a name='keyField'>keyField(**required**) - [String]</a>
|
||||
@ -50,7 +51,7 @@ Makes table rows selectable, please see [selectRow definition](./row-selection.m
|
||||
Custom the style of table rows:
|
||||
|
||||
```js
|
||||
<BootstrapTable data={ ... } columns={ ... } rowStyle={ { backgroundColor: 'red' } } />
|
||||
<BootstrapTable data={ data } columns={ columns } rowStyle={ { backgroundColor: 'red' } } />
|
||||
```
|
||||
|
||||
This prop also accept a callback function for flexible to custom row style:
|
||||
@ -60,14 +61,14 @@ const rowStyle = (row, rowIndex) => {
|
||||
return { ... };
|
||||
};
|
||||
|
||||
<BootstrapTable data={ ... } columns={ ... } rowStyle={ rowStyle } />
|
||||
<BootstrapTable data={ data } columns={ columns } rowStyle={ rowStyle } />
|
||||
```
|
||||
|
||||
### <a name='rowClasses'>rowClasses = [String | Function]</a>
|
||||
Custom the style of table rows:
|
||||
|
||||
```js
|
||||
<BootstrapTable data={ ... } columns={ ... } rowClasses="custom-row-class" />
|
||||
<BootstrapTable data={ data } columns={ columns } rowClasses="custom-row-class" />
|
||||
```
|
||||
|
||||
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';
|
||||
};
|
||||
|
||||
<BootstrapTable data={ ... } columns={ ... } rowClasses={ rowClasses } />
|
||||
<BootstrapTable data={ data } columns={ columns } rowClasses={ rowClasses } />
|
||||
```
|
||||
|
||||
### <a name='rowEvents'>rowEvents - [Object]</a>
|
||||
Custom the events on row:
|
||||
|
||||
```js
|
||||
const rowEvents = {
|
||||
onClick: (e) => {
|
||||
....
|
||||
}
|
||||
};
|
||||
<BootstrapTable data={ data } columns={ columns } rowEvents={ rowEvents } />
|
||||
```
|
||||
|
||||
### <a name='defaultSorted'>defaultSorted - [Array]</a>
|
||||
|
||||
54
packages/react-bootstrap-table2-example/examples/rows/row-event.js
vendored
Normal file
54
packages/react-bootstrap-table2-example/examples/rows/row-event.js
vendored
Normal file
@ -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');
|
||||
}
|
||||
};
|
||||
|
||||
<BootstrapTable keyField='id' data={ products } columns={ columns } rowStyle={ rowStyle } />
|
||||
`;
|
||||
|
||||
export default () => (
|
||||
<div>
|
||||
<BootstrapTable keyField="id" data={ products } columns={ columns } rowEvents={ rowEvents } />
|
||||
<Code>{ sourceCode }</Code>
|
||||
</div>
|
||||
);
|
||||
@ -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', () => <RowStyleTable />)
|
||||
.add('Customize Row Class', () => <RowClassTable />);
|
||||
.add('Customize Row Class', () => <RowClassTable />)
|
||||
.add('Row Event', () => <RowEventTable />);
|
||||
|
||||
storiesOf('Sort Table', module)
|
||||
.add('Enable Sort', () => <EnableSortTable />)
|
||||
|
||||
5
packages/react-bootstrap-table2/src/body.js
vendored
5
packages/react-bootstrap-table2/src/body.js
vendored
@ -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 }
|
||||
/>
|
||||
);
|
||||
});
|
||||
|
||||
@ -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 }
|
||||
/>
|
||||
</table>
|
||||
</div>
|
||||
@ -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,
|
||||
|
||||
46
packages/react-bootstrap-table2/src/row.js
vendored
46
packages/react-bootstrap-table2/src/row.js
vendored
@ -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;
|
||||
|
||||
@ -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(
|
||||
<Body
|
||||
{ ...mockBodyResolvedProps }
|
||||
keyField="id"
|
||||
columns={ columns }
|
||||
data={ data }
|
||||
rowEvents={ rowEvents }
|
||||
/>);
|
||||
});
|
||||
|
||||
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 = {
|
||||
|
||||
@ -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(
|
||||
<Row
|
||||
{ ...mockBodyResolvedProps }
|
||||
rowIndex={ rowIndex }
|
||||
columns={ defaultColumns }
|
||||
row={ row }
|
||||
attrs={ attrs }
|
||||
/>);
|
||||
});
|
||||
|
||||
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(
|
||||
<Row
|
||||
{ ...mockBodyResolvedProps }
|
||||
rowIndex={ rowIndex }
|
||||
columns={ defaultColumns }
|
||||
row={ row }
|
||||
selectRow={ selectRow }
|
||||
attrs={ attrs }
|
||||
selected
|
||||
selectable
|
||||
/>);
|
||||
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);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Loading…
Reference in New Issue
Block a user