diff --git a/packages/react-bootstrap-table2-example/examples/columns/row-expand-with-formatted-dummy-column.js b/packages/react-bootstrap-table2-example/examples/columns/row-expand-with-formatted-dummy-column.js new file mode 100644 index 0000000..a7a7ea3 --- /dev/null +++ b/packages/react-bootstrap-table2-example/examples/columns/row-expand-with-formatted-dummy-column.js @@ -0,0 +1,188 @@ +/* eslint no-param-reassign: 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 sourceCode = `\ +import BootstrapTable from 'react-bootstrap-table-next'; + +class DummyColumnWithRowExpand extends React.Component { + constructor(props) { + super(props); + + this.state = { + hoverIdx: null + }; + } + + expandRow = { + renderer: () => ( +
Content
+ ), + showExpandColumn: true, + expandByColumnOnly: true + }; + + actionFormater = (cell, row, rowIndex, { hoverIdx }) => { + if ((hoverIdx !== null || hoverIdx !== undefined) && hoverIdx === rowIndex) { + return ( +
+ ); + } + return ( +
+ ); + } + + rowEvents = { + onMouseEnter: (e, row, rowIndex) => { + this.setState({ hoverIdx: rowIndex }); + }, + onMouseLeave: () => { + this.setState({ hoverIdx: null }); + } + } + + rowStyle = (row, rowIndex) => { + row.index = rowIndex; + const style = {}; + if (rowIndex % 2 === 0) { + style.backgroundColor = 'transparent'; + } else { + style.backgroundColor = 'rgba(54, 163, 173, .10)'; + } + style.borderTop = 'none'; + + return style; + } + + render() { + const columns = [{ + dataField: 'id', + text: 'Product ID' + }, { + dataField: 'name', + text: 'Product Name' + }, { + dataField: 'price', + text: 'Product Price' + }, { + text: '', + isDummyField: true, + formatter: this.actionFormater, + formatExtraData: { hoverIdx: this.state.hoverIdx }, + headerStyle: { width: '50px' }, + style: { height: '30px' } + }]; + return ( +
+ +
+ ); + } +} +`; + +export default class DummyColumnWithRowExpand extends React.Component { + constructor(props) { + super(props); + + this.state = { + hoverIdx: null + }; + } + + expandRow = { + renderer: () => ( +
Content
+ ), + showExpandColumn: true, + expandByColumnOnly: true + }; + + actionFormater = (cell, row, rowIndex, { hoverIdx }) => { + if ((hoverIdx !== null || hoverIdx !== undefined) && hoverIdx === rowIndex) { + return ( +
+ ); + } + return ( +
+ ); + } + + rowEvents = { + onMouseEnter: (e, row, rowIndex) => { + this.setState({ hoverIdx: rowIndex }); + }, + onMouseLeave: () => { + this.setState({ hoverIdx: null }); + } + } + + rowStyle = (row, rowIndex) => { + row.index = rowIndex; + const style = {}; + if (rowIndex % 2 === 0) { + style.backgroundColor = 'transparent'; + } else { + style.backgroundColor = 'rgba(54, 163, 173, .10)'; + } + style.borderTop = 'none'; + + return style; + } + + render() { + const columns = [{ + dataField: 'id', + text: 'Product ID' + }, { + dataField: 'name', + text: 'Product Name' + }, { + dataField: 'price', + text: 'Product Price' + }, { + isDummyField: true, + text: '', + formatter: this.actionFormater, + formatExtraData: { hoverIdx: this.state.hoverIdx }, + headerStyle: { width: '50px' }, + style: { height: '30px' } + }]; + return ( +
+ + { sourceCode } +
+ ); + } +} diff --git a/packages/react-bootstrap-table2-example/examples/pagination/custom-pagination.js b/packages/react-bootstrap-table2-example/examples/pagination/custom-pagination.js index 4ea5164..f456904 100644 --- a/packages/react-bootstrap-table2-example/examples/pagination/custom-pagination.js +++ b/packages/react-bootstrap-table2-example/examples/pagination/custom-pagination.js @@ -74,7 +74,7 @@ const options = { // hidePageListOnlyOnePage: true, // Hide the pagination list when only one page firstPageText: 'First', prePageText: 'Back', - nextPageText: 'Next', + nextPageText: Next, lastPageText: 'Last', nextPageTitle: 'First page', prePageTitle: 'Pre page', diff --git a/packages/react-bootstrap-table2-example/stories/index.js b/packages/react-bootstrap-table2-example/stories/index.js index 2c71fac..732c5b2 100644 --- a/packages/react-bootstrap-table2-example/stories/index.js +++ b/packages/react-bootstrap-table2-example/stories/index.js @@ -35,6 +35,7 @@ import ColumnEventTable from 'examples/columns/column-event-table'; import ColumnHiddenTable from 'examples/columns/column-hidden-table'; import ColumnAttrsTable from 'examples/columns/column-attrs-table'; import DummyColumnTable from 'examples/columns/dummy-column-table'; +import RowExpandWithFormattedDummyColumn from 'examples/columns/row-expand-with-formatted-dummy-column.js'; // work on header columns import HeaderColumnFormatTable from 'examples/header-columns/column-format-table'; @@ -273,7 +274,8 @@ storiesOf('Work on Columns', module) .add('Customize Column Class', () => ) .add('Customize Column Style', () => ) .add('Customize Column HTML attribute', () => ) - .add('Dummy Column', () => ); + .add('Dummy Column', () => ) + .add('Row Expand with Dummy Column Formatter', () => ); storiesOf('Work on Header Columns', module) .addDecorator(bootstrapStyle()) diff --git a/packages/react-bootstrap-table2-filter/src/components/multiselect.js b/packages/react-bootstrap-table2-filter/src/components/multiselect.js index 2de86f9..66ad4a0 100644 --- a/packages/react-bootstrap-table2-filter/src/components/multiselect.js +++ b/packages/react-bootstrap-table2-filter/src/components/multiselect.js @@ -18,8 +18,18 @@ function optionsEquals(currOpts, prevOpts) { return Object.keys(currOpts).length === Object.keys(prevOpts).length; } -const getSelections = container => - Array.from(container.selectedOptions).map(item => item.value); +const getSelections = (container) => { + if (container.selectedOptions) { + return Array.from(container.selectedOptions).map(item => item.value); + } + const selections = []; + const totalLen = container.options.length; + for (let i = 0; i < totalLen; i += 1) { + const option = container.options.item(i); + if (option.selected) selections.push(option.value); + } + return selections; +}; class MultiSelectFilter extends Component { constructor(props) { diff --git a/packages/react-bootstrap-table2-paginator/src/page-button.js b/packages/react-bootstrap-table2-paginator/src/page-button.js index e2834ee..d3a81fb 100644 --- a/packages/react-bootstrap-table2-paginator/src/page-button.js +++ b/packages/react-bootstrap-table2-paginator/src/page-button.js @@ -39,7 +39,11 @@ class PageButton extends Component { PageButton.propTypes = { onPageChange: PropTypes.func.isRequired, - page: PropTypes.oneOfType([PropTypes.number, PropTypes.string]).isRequired, + page: PropTypes.oneOfType([ + PropTypes.node, + PropTypes.number, + PropTypes.string + ]).isRequired, active: PropTypes.bool.isRequired, disabled: PropTypes.bool.isRequired, className: PropTypes.string, diff --git a/packages/react-bootstrap-table2-paginator/src/pagination-list.js b/packages/react-bootstrap-table2-paginator/src/pagination-list.js index 9954538..d9454c6 100644 --- a/packages/react-bootstrap-table2-paginator/src/pagination-list.js +++ b/packages/react-bootstrap-table2-paginator/src/pagination-list.js @@ -27,7 +27,11 @@ const PaginatonList = props => ( PaginatonList.propTypes = { pages: PropTypes.arrayOf(PropTypes.shape({ - page: PropTypes.oneOfType([PropTypes.number, PropTypes.string]), + page: PropTypes.oneOfType([ + PropTypes.node, + PropTypes.number, + PropTypes.string + ]), active: PropTypes.bool, disable: PropTypes.bool, title: PropTypes.string diff --git a/packages/react-bootstrap-table2-paginator/src/pagination.js b/packages/react-bootstrap-table2-paginator/src/pagination.js index fa2bd86..d967642 100644 --- a/packages/react-bootstrap-table2-paginator/src/pagination.js +++ b/packages/react-bootstrap-table2-paginator/src/pagination.js @@ -100,10 +100,10 @@ Pagination.propTypes = { sizePerPageRenderer: PropTypes.func, paginationTotalRenderer: PropTypes.func, sizePerPageOptionRenderer: PropTypes.func, - firstPageText: PropTypes.string, - prePageText: PropTypes.string, - nextPageText: PropTypes.string, - lastPageText: PropTypes.string, + firstPageText: PropTypes.oneOfType([PropTypes.string, PropTypes.node]), + prePageText: PropTypes.oneOfType([PropTypes.string, PropTypes.node]), + nextPageText: PropTypes.oneOfType([PropTypes.string, PropTypes.node]), + lastPageText: PropTypes.oneOfType([PropTypes.string, PropTypes.node]), nextPageTitle: PropTypes.string, prePageTitle: PropTypes.string, firstPageTitle: PropTypes.string, diff --git a/packages/react-bootstrap-table2/src/cell-event-delegater.js b/packages/react-bootstrap-table2/src/cell-event-delegater.js index 41e0f71..14c2fa0 100644 --- a/packages/react-bootstrap-table2/src/cell-event-delegater.js +++ b/packages/react-bootstrap-table2/src/cell-event-delegater.js @@ -1,3 +1,5 @@ +import _ from './utils'; + const events = [ 'onClick', 'onDoubleClick', @@ -23,7 +25,7 @@ export default ExtendBase => delegate(attrs = {}) { const newAttrs = { ...attrs }; Object.keys(attrs).forEach((attr) => { - if (events.includes(attr)) { + if (_.contains(events, attr)) { newAttrs[attr] = this.createDefaultEventHandler(attrs[attr]); } }); diff --git a/packages/react-bootstrap-table2/src/contexts/row-expand-context.js b/packages/react-bootstrap-table2/src/contexts/row-expand-context.js index eef22a7..e1c5e47 100644 --- a/packages/react-bootstrap-table2/src/contexts/row-expand-context.js +++ b/packages/react-bootstrap-table2/src/contexts/row-expand-context.js @@ -20,7 +20,7 @@ class RowExpandProvider extends React.Component { if (nextProps.expandRow) { const nextExpanded = nextProps.expandRow.expanded || this.state.expanded; const isClosing = this.state.expanded.reduce((acc, cur) => { - if (!nextExpanded.includes(cur)) { + if (!_.contains(nextExpanded, cur)) { acc.push(cur); } return acc; @@ -42,7 +42,7 @@ class RowExpandProvider extends React.Component { handleRowExpand = (rowKey, expanded, rowIndex, e) => { const { data, keyField, expandRow: { onExpand, onlyOneExpanding, nonExpandable } } = this.props; - if (nonExpandable && nonExpandable.includes(rowKey)) { + if (nonExpandable && _.contains(nonExpandable, rowKey)) { return; } diff --git a/packages/react-bootstrap-table2/src/props-resolver/index.js b/packages/react-bootstrap-table2/src/props-resolver/index.js index 92ae62d..5e18b27 100644 --- a/packages/react-bootstrap-table2/src/props-resolver/index.js +++ b/packages/react-bootstrap-table2/src/props-resolver/index.js @@ -22,7 +22,7 @@ export default ExtendBase => if (!hiddenRows || hiddenRows.length === 0) return data; return data.filter((row) => { const key = _.get(row, keyField); - return !hiddenRows.includes(key); + return !_.contains(hiddenRows, key); }); } }; diff --git a/packages/react-bootstrap-table2/src/row-expand/row-consumer.js b/packages/react-bootstrap-table2/src/row-expand/row-consumer.js index 724b5d2..e0decc4 100644 --- a/packages/react-bootstrap-table2/src/row-expand/row-consumer.js +++ b/packages/react-bootstrap-table2/src/row-expand/row-consumer.js @@ -1,15 +1,16 @@ /* eslint react/prop-types: 0 */ import React from 'react'; import ExpandRow from './expand-row'; +import _ from '../utils'; import ExpansionContext from '../contexts/row-expand-context'; export default (Component) => { const renderWithExpansion = (props, expandRow) => { const key = props.value; - const expanded = expandRow.expanded.includes(key); - const isClosing = expandRow.isClosing.includes(key); - const expandable = !expandRow.nonExpandable || !expandRow.nonExpandable.includes(key); + const expanded = _.contains(expandRow.expanded, key); + const isClosing = _.contains(expandRow.isClosing, key); + const expandable = !expandRow.nonExpandable || !_.contains(expandRow.nonExpandable, key); return [ { const renderWithSelection = (props, selectRow) => { const key = props.value; - const selected = selectRow.selected.includes(key); - const selectable = !selectRow.nonSelectable || !selectRow.nonSelectable.includes(key); + const selected = _.contains(selectRow.selected, key); + const selectable = !selectRow.nonSelectable || !_.contains(selectRow.nonSelectable, key); let { style, diff --git a/packages/react-bootstrap-table2/src/row/aggregate-row.js b/packages/react-bootstrap-table2/src/row/aggregate-row.js index 3a151db..f0d9187 100644 --- a/packages/react-bootstrap-table2/src/row/aggregate-row.js +++ b/packages/react-bootstrap-table2/src/row/aggregate-row.js @@ -37,10 +37,10 @@ export default class RowAggregator extends shouldUpdater(eventDelegater(React.Co this.props.selectable !== nextProps.selectable || this.shouldUpdatedBySelfProps(nextProps) ) { - this.shouldUpdateRowContent = this.shouldUpdateChild(nextProps); + this.shouldUpdateRowContent = this.shouldRowContentUpdate(nextProps); return true; } - this.shouldUpdateRowContent = this.shouldUpdateChild(nextProps); + this.shouldUpdateRowContent = this.shouldRowContentUpdate(nextProps); return this.shouldUpdateRowContent; } diff --git a/packages/react-bootstrap-table2/src/row/event-delegater.js b/packages/react-bootstrap-table2/src/row/event-delegater.js index 0a17aa2..a6a1a1f 100644 --- a/packages/react-bootstrap-table2/src/row/event-delegater.js +++ b/packages/react-bootstrap-table2/src/row/event-delegater.js @@ -74,7 +74,7 @@ export default ExtendBase => delegate(attrs = {}) { const newAttrs = { ...attrs }; Object.keys(attrs).forEach((attr) => { - if (events.includes(attr)) { + if (_.contains(events, attr)) { newAttrs[attr] = this.createDefaultEventHandler(attrs[attr]); } }); diff --git a/packages/react-bootstrap-table2/src/row/should-updater.js b/packages/react-bootstrap-table2/src/row/should-updater.js index c61ae5e..fb1f1be 100644 --- a/packages/react-bootstrap-table2/src/row/should-updater.js +++ b/packages/react-bootstrap-table2/src/row/should-updater.js @@ -48,4 +48,9 @@ export default ExtendBase => return this.shouldUpdateByCellEditing(nextProps) || this.shouldUpdatedByNormalProps(nextProps); } + + shouldRowContentUpdate(nextProps) { + return this.shouldUpdateChild(nextProps) || + this.shouldUpdateByColumnsForSimpleCheck(nextProps); + } }; diff --git a/packages/react-bootstrap-table2/src/row/simple-row.js b/packages/react-bootstrap-table2/src/row/simple-row.js index 96ca92f..0ad992f 100644 --- a/packages/react-bootstrap-table2/src/row/simple-row.js +++ b/packages/react-bootstrap-table2/src/row/simple-row.js @@ -15,8 +15,7 @@ class SimpleRow extends shouldUpdater(eventDelegater(Component)) { shouldComponentUpdate(nextProps) { this.shouldUpdateRowContent = false; - this.shouldUpdateRowContent = - this.shouldUpdateChild(nextProps) || this.shouldUpdateByColumnsForSimpleCheck(nextProps); + this.shouldUpdateRowContent = this.shouldRowContentUpdate(nextProps); if (this.shouldUpdateRowContent) return true; return this.shouldUpdatedBySelfProps(nextProps); diff --git a/packages/react-bootstrap-table2/src/store/expand.js b/packages/react-bootstrap-table2/src/store/expand.js index 31feb0a..ceefae7 100644 --- a/packages/react-bootstrap-table2/src/store/expand.js +++ b/packages/react-bootstrap-table2/src/store/expand.js @@ -20,7 +20,7 @@ export const expandableKeys = (data, keyField, skips = []) => { return data.map(row => _.get(row, keyField)); } return data - .filter(row => !skips.includes(_.get(row, keyField))) + .filter(row => !_.contains(skips, _.get(row, keyField))) .map(row => _.get(row, keyField)); }; diff --git a/packages/react-bootstrap-table2/src/store/selection.js b/packages/react-bootstrap-table2/src/store/selection.js index af6a8c1..38ecd5f 100644 --- a/packages/react-bootstrap-table2/src/store/selection.js +++ b/packages/react-bootstrap-table2/src/store/selection.js @@ -29,7 +29,7 @@ export const selectableKeys = (data, keyField, skips = []) => { return data.map(row => _.get(row, keyField)); } return data - .filter(row => !skips.includes(_.get(row, keyField))) + .filter(row => !_.contains(skips, _.get(row, keyField))) .map(row => _.get(row, keyField)); }; @@ -37,7 +37,7 @@ export const unSelectableKeys = (selected, skips = []) => { if (skips.length === 0) { return []; } - return selected.filter(x => skips.includes(x)); + return selected.filter(x => _.contains(skips, x)); }; export const getSelectedRows = (data, keyField, selected) =>