From a8083ac17d4a19e9feb25e32ceb33177998d270f Mon Sep 17 00:00:00 2001 From: Parth Prajapati Date: Sat, 24 Feb 2018 20:23:52 +0530 Subject: [PATCH 1/7] Fixes #186 (#219) * Fixes #186 * Solved lint error --- packages/react-bootstrap-table2/src/bootstrap-table.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/react-bootstrap-table2/src/bootstrap-table.js b/packages/react-bootstrap-table2/src/bootstrap-table.js index 4834ec0..dae3893 100644 --- a/packages/react-bootstrap-table2/src/bootstrap-table.js +++ b/packages/react-bootstrap-table2/src/bootstrap-table.js @@ -70,10 +70,12 @@ class BootstrapTable extends PropsBaseResolver(Component) { allRowsSelected: isSelectedAll(store) }); + const tableCaption = (caption && { caption }); + return (
- + { tableCaption }
Date: Sat, 24 Feb 2018 23:03:09 +0800 Subject: [PATCH 2/7] fix #221 --- packages/react-bootstrap-table2-editor/src/text-editor.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/react-bootstrap-table2-editor/src/text-editor.js b/packages/react-bootstrap-table2-editor/src/text-editor.js index 52233e7..7937282 100644 --- a/packages/react-bootstrap-table2-editor/src/text-editor.js +++ b/packages/react-bootstrap-table2-editor/src/text-editor.js @@ -32,9 +32,10 @@ TextEditor.propTypes = { defaultValue: PropTypes.oneOfType([ PropTypes.string, PropTypes.number - ]).isRequired + ]) }; TextEditor.defaultProps = { - className: null + className: null, + defaultValue: '' }; export default TextEditor; From 931cf8045045c3fdb7ce8e3945ebac76f9730965 Mon Sep 17 00:00:00 2001 From: Parth Prajapati Date: Sat, 24 Feb 2018 20:23:52 +0530 Subject: [PATCH 3/7] Fixes #186 (#219) * Fixes #186 * Solved lint error --- packages/react-bootstrap-table2/src/bootstrap-table.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/react-bootstrap-table2/src/bootstrap-table.js b/packages/react-bootstrap-table2/src/bootstrap-table.js index 4834ec0..dae3893 100644 --- a/packages/react-bootstrap-table2/src/bootstrap-table.js +++ b/packages/react-bootstrap-table2/src/bootstrap-table.js @@ -70,10 +70,12 @@ class BootstrapTable extends PropsBaseResolver(Component) { allRowsSelected: isSelectedAll(store) }); + const tableCaption = (caption &&
); + return (
{ caption }{ caption }
- + { tableCaption }
Date: Sat, 24 Feb 2018 23:03:09 +0800 Subject: [PATCH 4/7] fix #221 --- packages/react-bootstrap-table2-editor/src/text-editor.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/react-bootstrap-table2-editor/src/text-editor.js b/packages/react-bootstrap-table2-editor/src/text-editor.js index 52233e7..7937282 100644 --- a/packages/react-bootstrap-table2-editor/src/text-editor.js +++ b/packages/react-bootstrap-table2-editor/src/text-editor.js @@ -32,9 +32,10 @@ TextEditor.propTypes = { defaultValue: PropTypes.oneOfType([ PropTypes.string, PropTypes.number - ]).isRequired + ]) }; TextEditor.defaultProps = { - className: null + className: null, + defaultValue: '' }; export default TextEditor; From a11913c49a10b80a31c35a2c2b02e075b8ed3e61 Mon Sep 17 00:00:00 2001 From: Allen Date: Sun, 4 Mar 2018 16:21:10 +0800 Subject: [PATCH 5/7] fix #210 (#232) --- .../examples/sort/enable-sort-table.js | 31 +++++++++++++++---- .../src/sort/wrapper.js | 10 +++--- .../test/sort/wrapper.test.js | 26 +++------------- 3 files changed, 33 insertions(+), 34 deletions(-) diff --git a/packages/react-bootstrap-table2-example/examples/sort/enable-sort-table.js b/packages/react-bootstrap-table2-example/examples/sort/enable-sort-table.js index 16e628f..7d0d406 100644 --- a/packages/react-bootstrap-table2-example/examples/sort/enable-sort-table.js +++ b/packages/react-bootstrap-table2-example/examples/sort/enable-sort-table.js @@ -38,9 +38,28 @@ const columns = [{ `; -export default () => ( -
- - { sourceCode } -
-); +export default class Test extends React.Component { + constructor(props) { + super(props); + this.state = { data: products }; + } + + handleClick = () => { + this.setState(() => { + const newProducts = productsGenerator(21); + return { + data: newProducts + }; + }); + } + + render() { + return ( +
+ + + { sourceCode } +
+ ); + } +} diff --git a/packages/react-bootstrap-table2/src/sort/wrapper.js b/packages/react-bootstrap-table2/src/sort/wrapper.js index 90a9bb9..71c5051 100644 --- a/packages/react-bootstrap-table2/src/sort/wrapper.js +++ b/packages/react-bootstrap-table2/src/sort/wrapper.js @@ -39,12 +39,10 @@ export default Base => } componentWillReceiveProps(nextProps) { - if (nextProps.isDataChanged) { - const sortedColumn = nextProps.columns.find( - column => column.dataField === nextProps.store.sortField); - if (sortedColumn) { - nextProps.store.sortBy(sortedColumn); - } + const sortedColumn = nextProps.columns.find( + column => column.dataField === nextProps.store.sortField); + if (sortedColumn && sortedColumn.sort) { + nextProps.store.sortBy(sortedColumn); } } diff --git a/packages/react-bootstrap-table2/test/sort/wrapper.test.js b/packages/react-bootstrap-table2/test/sort/wrapper.test.js index 1c28b8c..2575e86 100644 --- a/packages/react-bootstrap-table2/test/sort/wrapper.test.js +++ b/packages/react-bootstrap-table2/test/sort/wrapper.test.js @@ -219,30 +219,12 @@ describe('SortWrapper', () => { nextProps = { columns, store }; store.sortField = columns[1].dataField; store.sortOrder = Const.SORT_DESC; + store.sortBy = sinon.stub(); }); - describe('if nextProps.isDataChanged is true', () => { - beforeEach(() => { - nextProps.isDataChanged = true; - store.sortBy = sinon.stub(); - }); - - it('should sorting again', () => { - wrapper.instance().componentWillReceiveProps(nextProps); - expect(store.sortBy.calledOnce).toBeTruthy(); - }); - }); - - describe('if nextProps.isDataChanged is false', () => { - beforeEach(() => { - nextProps.isDataChanged = false; - store.sortBy = sinon.stub(); - }); - - it('should not sorting', () => { - wrapper.instance().componentWillReceiveProps(nextProps); - expect(store.sortBy.calledOnce).toBeFalsy(); - }); + it('should sorting again', () => { + wrapper.instance().componentWillReceiveProps(nextProps); + expect(store.sortBy.calledOnce).toBeTruthy(); }); }); }); From 9382ed587b3bf30623a03c6a0b11f05d7013b065 Mon Sep 17 00:00:00 2001 From: Allen Date: Sun, 4 Mar 2018 17:22:52 +0800 Subject: [PATCH 6/7] implement row event delegater (#233) --- .../src/row-event-delegater.js | 84 +++++++++++++++++++ packages/react-bootstrap-table2/src/row.js | 72 +--------------- .../react-bootstrap-table2/test/row.test.js | 6 +- 3 files changed, 92 insertions(+), 70 deletions(-) create mode 100644 packages/react-bootstrap-table2/src/row-event-delegater.js diff --git a/packages/react-bootstrap-table2/src/row-event-delegater.js b/packages/react-bootstrap-table2/src/row-event-delegater.js new file mode 100644 index 0000000..a35de46 --- /dev/null +++ b/packages/react-bootstrap-table2/src/row-event-delegater.js @@ -0,0 +1,84 @@ +import _ from './utils'; + +const events = [ + 'onClick', + 'onMouseEnter', + 'onMouseLeave' +]; + +export default ExtendBase => + class RowEventDelegater extends ExtendBase { + constructor(props) { + super(props); + this.clickNum = 0; + this.createDefaultEventHandler = this.createDefaultEventHandler.bind(this); + this.createClickEventHandler = this.createClickEventHandler.bind(this); + } + + createDefaultEventHandler(cb) { + return (e) => { + const { row, rowIndex } = this.props; + cb(e, row, rowIndex); + }; + } + + createClickEventHandler(cb) { + return (e) => { + const { + row, + selected, + keyField, + selectable, + rowIndex, + selectRow: { + onRowSelect, + clickToEdit + }, + cellEdit: { + mode, + DBCLICK_TO_CELL_EDIT, + DELAY_FOR_DBCLICK + } + } = this.props; + + const clickFn = () => { + if (cb) { + cb(e, row, rowIndex); + } + if (selectable) { + const key = _.get(row, keyField); + onRowSelect(key, !selected, rowIndex); + } + }; + + if (mode === DBCLICK_TO_CELL_EDIT && clickToEdit) { + this.clickNum += 1; + _.debounce(() => { + if (this.clickNum === 1) { + clickFn(); + } + this.clickNum = 0; + }, DELAY_FOR_DBCLICK)(); + } else { + clickFn(); + } + }; + } + + delegate(attrs = {}) { + const newAttrs = {}; + if (this.props.selectRow && this.props.selectRow.clickToSelect) { + newAttrs.onClick = this.createClickEventHandler(attrs.onClick); + } + Object.keys(attrs).forEach((attr) => { + if (!newAttrs[attr]) { + if (events.includes(attr)) { + newAttrs[attr] = this.createDefaultEventHandler(attrs[attr]); + } else { + newAttrs[attr] = attrs[attr]; + } + } + }); + return newAttrs; + } + }; diff --git a/packages/react-bootstrap-table2/src/row.js b/packages/react-bootstrap-table2/src/row.js index 1b55628..7b1df37 100644 --- a/packages/react-bootstrap-table2/src/row.js +++ b/packages/react-bootstrap-table2/src/row.js @@ -6,68 +6,10 @@ import PropTypes from 'prop-types'; import _ from './utils'; import Cell from './cell'; import SelectionCell from './row-selection/selection-cell'; +import eventDelegater from './row-event-delegater'; import Const from './const'; -class Row extends Component { - constructor(props) { - super(props); - this.clickNum = 0; - this.handleRowClick = this.handleRowClick.bind(this); - this.handleSimpleRowClick = this.handleSimpleRowClick.bind(this); - } - - handleRowClick(e) { - const { - row, - selected, - keyField, - selectable, - rowIndex, - selectRow: { - onRowSelect, - clickToEdit - }, - cellEdit: { - mode, - DBCLICK_TO_CELL_EDIT, - DELAY_FOR_DBCLICK - }, - attrs - } = this.props; - - const clickFn = () => { - if (attrs.onClick) { - attrs.onClick(e, row, rowIndex); - } - if (selectable) { - const key = _.get(row, keyField); - onRowSelect(key, !selected, rowIndex); - } - }; - - if (mode === DBCLICK_TO_CELL_EDIT && clickToEdit) { - this.clickNum += 1; - _.debounce(() => { - if (this.clickNum === 1) { - clickFn(); - } - this.clickNum = 0; - }, DELAY_FOR_DBCLICK)(); - } else { - clickFn(); - } - } - - handleSimpleRowClick(e) { - const { - row, - rowIndex, - attrs - } = this.props; - - attrs.onClick(e, row, rowIndex); - } - +class Row extends eventDelegater(Component) { render() { const { row, @@ -96,14 +38,8 @@ class Row extends Component { } = cellEdit; const key = _.get(row, keyField); - const { clickToSelect, hideSelectColumn } = selectRow; - - const trAttrs = { ...attrs }; - if (clickToSelect) { - trAttrs.onClick = this.handleRowClick; - } else if (attrs.onClick) { - trAttrs.onClick = this.handleSimpleRowClick; - } + const { hideSelectColumn } = selectRow; + const trAttrs = this.delegate(attrs); return (
diff --git a/packages/react-bootstrap-table2/test/row.test.js b/packages/react-bootstrap-table2/test/row.test.js index 955a421..02cc068 100644 --- a/packages/react-bootstrap-table2/test/row.test.js +++ b/packages/react-bootstrap-table2/test/row.test.js @@ -799,8 +799,10 @@ describe('Row', () => { selected selectable />); - wrapper.instance().handleRowClick(); - wrapper.instance().handleRowClick(); + // console.log(wrapper.instance()); + const rowClick = wrapper.instance().createClickEventHandler(); + rowClick(); + rowClick(); }); it('should increase clickNum as 2', () => { From a5cb806d9851c1f45c2cf770e4d4e036f8ea2a0d Mon Sep 17 00:00:00 2001 From: Allen Date: Mon, 5 Mar 2018 22:27:46 +0800 Subject: [PATCH 7/7] implement default selection (#234) --- docs/row-selection.md | 11 ++++ .../examples/row-selection/default-select.js | 59 +++++++++++++++++++ .../stories/index.js | 2 + .../src/row-selection/wrapper.js | 11 ++++ .../test/row-selection/wrapper.test.js | 36 +++++++++-- 5 files changed, 115 insertions(+), 4 deletions(-) create mode 100644 packages/react-bootstrap-table2-example/examples/row-selection/default-select.js diff --git a/docs/row-selection.md b/docs/row-selection.md index e50ef83..c877e6b 100644 --- a/docs/row-selection.md +++ b/docs/row-selection.md @@ -6,6 +6,7 @@ * [mode (**required**)](#mode) ## Optional +* [selected](#selected) * [style](#style) * [classes)](#classes) * [bgColor](#bgColor) @@ -52,6 +53,16 @@ const selectRow = { /> ``` +### selectRow.selected - [Array] +`selectRow.selected` allow you have default selections on table. + +```js +const selectRow = { + mode: 'checkbox', + selected: [1, 3] // should be a row keys array +}; +``` + ### selectRow.style - [Object | Function] `selectRow.style` allow you to have custom style on selected rows: diff --git a/packages/react-bootstrap-table2-example/examples/row-selection/default-select.js b/packages/react-bootstrap-table2-example/examples/row-selection/default-select.js new file mode 100644 index 0000000..d11a688 --- /dev/null +++ b/packages/react-bootstrap-table2-example/examples/row-selection/default-select.js @@ -0,0 +1,59 @@ +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' +}, { + dataField: 'name', + text: 'Product Name' +}, { + dataField: 'price', + text: 'Product Price' +}]; + +const selectRow = { + mode: 'checkbox', + clickToSelect: true, + selected: [1, 3] +}; + +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' +}]; + +const selectRow = { + mode: 'checkbox', + clickToSelect: true, + selected: [1, 3] +}; + + +`; + +export default () => ( +
+ + { sourceCode } +
+); diff --git a/packages/react-bootstrap-table2-example/stories/index.js b/packages/react-bootstrap-table2-example/stories/index.js index 09bce47..b7444a7 100644 --- a/packages/react-bootstrap-table2-example/stories/index.js +++ b/packages/react-bootstrap-table2-example/stories/index.js @@ -77,6 +77,7 @@ import CellEditClassTable from 'examples/cell-edit/cell-edit-class-table'; import SingleSelectionTable from 'examples/row-selection/single-selection'; import MultipleSelectionTable from 'examples/row-selection/multiple-selection'; import ClickToSelectTable from 'examples/row-selection/click-to-select'; +import DefaultSelectTable from 'examples/row-selection/default-select'; import ClickToSelectWithCellEditTable from 'examples/row-selection/click-to-select-with-cell-edit'; import SelectionStyleTable from 'examples/row-selection/selection-style'; import SelectionClassTable from 'examples/row-selection/selection-class'; @@ -189,6 +190,7 @@ storiesOf('Row Selection', module) .add('Single Selection', () => ) .add('Multiple Selection', () => ) .add('Click to Select', () => ) + .add('Default Select', () => ) .add('Click to Select and Edit Cell', () => ) .add('Selection Style', () => ) .add('Selection Class', () => ) diff --git a/packages/react-bootstrap-table2/src/row-selection/wrapper.js b/packages/react-bootstrap-table2/src/row-selection/wrapper.js index 442cb18..b8c79bd 100644 --- a/packages/react-bootstrap-table2/src/row-selection/wrapper.js +++ b/packages/react-bootstrap-table2/src/row-selection/wrapper.js @@ -1,3 +1,4 @@ +/* eslint no-param-reassign: 0 */ import React, { Component } from 'react'; import PropTypes from 'prop-types'; @@ -21,11 +22,21 @@ export default Base => super(props); this.handleRowSelect = this.handleRowSelect.bind(this); this.handleAllRowsSelect = this.handleAllRowsSelect.bind(this); + props.store.selected = this.props.selectRow.selected || []; this.state = { selectedRowKeys: props.store.selected }; } + componentWillReceiveProps(nextProps) { + if (nextProps.selectRow) { + this.store.selected = nextProps.selectRow.selected || []; + this.setState(() => ({ + selectedRowKeys: this.store.selected + })); + } + } + /** * row selection handler * @param {String} rowKey - row key of what was selected. diff --git a/packages/react-bootstrap-table2/test/row-selection/wrapper.test.js b/packages/react-bootstrap-table2/test/row-selection/wrapper.test.js index fba2c67..278a54e 100644 --- a/packages/react-bootstrap-table2/test/row-selection/wrapper.test.js +++ b/packages/react-bootstrap-table2/test/row-selection/wrapper.test.js @@ -8,6 +8,7 @@ import wrapperFactory from '../../src/row-selection/wrapper'; describe('RowSelectionWrapper', () => { let wrapper; + let selectRow; const columns = [{ dataField: 'id', @@ -25,10 +26,6 @@ describe('RowSelectionWrapper', () => { name: 'B' }]; - const selectRow = { - mode: 'radio' - }; - const rowIndex = 1; const keyField = 'id'; @@ -38,6 +35,9 @@ describe('RowSelectionWrapper', () => { const RowSelectionWrapper = wrapperFactory(BootstrapTable); beforeEach(() => { + selectRow = { + mode: 'radio' + }; wrapper = shallow( { expect(wrapper.find(BootstrapTable)).toBeDefined(); }); + it('should have correct store.selected value', () => { + expect(store.selected).toEqual([]); + }); + it('should have correct state', () => { expect(wrapper.state().selectedRowKeys).toBeDefined(); expect(wrapper.state().selectedRowKeys.length).toEqual(0); @@ -64,6 +68,30 @@ describe('RowSelectionWrapper', () => { expect(wrapper.props().onAllRowsSelect).toBeDefined(); }); + describe('when selectRow.selected is defiend', () => { + beforeEach(() => { + selectRow.mode = 'checkbox'; + selectRow.selected = [1, 3]; + wrapper = shallow( + + ); + }); + + it('should have correct store.selected value', () => { + expect(store.selected).toEqual(selectRow.selected); + }); + + it('should have correct state', () => { + expect(wrapper.state().selectedRowKeys).toEqual(selectRow.selected); + }); + }); + describe('when selectRow.mode is \'radio\'', () => { const firstSelectedRow = data[0][keyField]; const secondSelectedRow = data[1][keyField];
{ caption }