mirror of
https://github.com/gosticks/react-bootstrap-table2.git
synced 2025-10-16 11:55:39 +00:00
implement expand row sketch
This commit is contained in:
parent
6eaffe1993
commit
35b1e37940
26
packages/react-bootstrap-table2/src/body.js
vendored
26
packages/react-bootstrap-table2/src/body.js
vendored
@ -7,6 +7,7 @@ import cs from 'classnames';
|
|||||||
|
|
||||||
import _ from './utils';
|
import _ from './utils';
|
||||||
import Row from './row';
|
import Row from './row';
|
||||||
|
import ExpandRow from './row-expand/expand-row';
|
||||||
import RowSection from './row-section';
|
import RowSection from './row-section';
|
||||||
import Const from './const';
|
import Const from './const';
|
||||||
|
|
||||||
@ -23,7 +24,8 @@ const Body = (props) => {
|
|||||||
selectedRowKeys,
|
selectedRowKeys,
|
||||||
rowStyle,
|
rowStyle,
|
||||||
rowClasses,
|
rowClasses,
|
||||||
rowEvents
|
rowEvents,
|
||||||
|
expandRow
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
const {
|
const {
|
||||||
@ -74,8 +76,10 @@ const Body = (props) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const selectable = !nonSelectable || !nonSelectable.includes(key);
|
const selectable = !nonSelectable || !nonSelectable.includes(key);
|
||||||
|
const expandable = expandRow && !expandRow.nonExpandable.includes(key);
|
||||||
|
const expanded = expandRow && expandRow.expanded.includes(key);
|
||||||
|
|
||||||
return (
|
const result = [
|
||||||
<Row
|
<Row
|
||||||
key={ key }
|
key={ key }
|
||||||
row={ row }
|
row={ row }
|
||||||
@ -85,13 +89,29 @@ const Body = (props) => {
|
|||||||
cellEdit={ cellEdit }
|
cellEdit={ cellEdit }
|
||||||
editable={ editable }
|
editable={ editable }
|
||||||
selectable={ selectable }
|
selectable={ selectable }
|
||||||
|
expandable={ expandable }
|
||||||
selected={ selected }
|
selected={ selected }
|
||||||
|
expanded={ expanded }
|
||||||
selectRow={ selectRow }
|
selectRow={ selectRow }
|
||||||
|
expandRow={ expandRow }
|
||||||
style={ style }
|
style={ style }
|
||||||
className={ classes }
|
className={ classes }
|
||||||
attrs={ attrs }
|
attrs={ attrs }
|
||||||
/>
|
/>
|
||||||
);
|
];
|
||||||
|
|
||||||
|
if (expanded) {
|
||||||
|
result.push((
|
||||||
|
<ExpandRow
|
||||||
|
key={ `${key}-expanding` }
|
||||||
|
colSpan={ visibleColumnSize }
|
||||||
|
>
|
||||||
|
{ expandRow.renderer(row) }
|
||||||
|
</ExpandRow>
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -97,6 +97,7 @@ class BootstrapTable extends PropsBaseResolver(Component) {
|
|||||||
cellEdit={ this.props.cellEdit || {} }
|
cellEdit={ this.props.cellEdit || {} }
|
||||||
selectRow={ cellSelectionInfo }
|
selectRow={ cellSelectionInfo }
|
||||||
selectedRowKeys={ selected }
|
selectedRowKeys={ selected }
|
||||||
|
expandRow={ this.resolveExpandRowProps() }
|
||||||
rowStyle={ rowStyle }
|
rowStyle={ rowStyle }
|
||||||
rowClasses={ rowClasses }
|
rowClasses={ rowClasses }
|
||||||
rowEvents={ rowEvents }
|
rowEvents={ rowEvents }
|
||||||
@ -145,6 +146,14 @@ BootstrapTable.propTypes = {
|
|||||||
}),
|
}),
|
||||||
onRowSelect: PropTypes.func,
|
onRowSelect: PropTypes.func,
|
||||||
onAllRowsSelect: PropTypes.func,
|
onAllRowsSelect: PropTypes.func,
|
||||||
|
expandRow: PropTypes.shape({
|
||||||
|
renderer: PropTypes.func.isRequired,
|
||||||
|
expanded: PropTypes.array,
|
||||||
|
nonExpandable: PropTypes.array,
|
||||||
|
showExpandColumn: PropTypes.bool,
|
||||||
|
expandColumnRenderer: PropTypes.func
|
||||||
|
}),
|
||||||
|
onRowExpand: PropTypes.func,
|
||||||
rowStyle: PropTypes.oneOfType([PropTypes.object, PropTypes.func]),
|
rowStyle: PropTypes.oneOfType([PropTypes.object, PropTypes.func]),
|
||||||
rowEvents: PropTypes.object,
|
rowEvents: PropTypes.object,
|
||||||
rowClasses: PropTypes.oneOfType([PropTypes.string, PropTypes.func]),
|
rowClasses: PropTypes.oneOfType([PropTypes.string, PropTypes.func]),
|
||||||
|
|||||||
@ -5,6 +5,7 @@ import _ from '../utils';
|
|||||||
import createDataContext from './data-context';
|
import createDataContext from './data-context';
|
||||||
import createSortContext from './sort-context';
|
import createSortContext from './sort-context';
|
||||||
import createSelectionContext from './selection-context';
|
import createSelectionContext from './selection-context';
|
||||||
|
import createRowExpandContext from './row-expand-context';
|
||||||
import remoteResolver from '../props-resolver/remote-resolver';
|
import remoteResolver from '../props-resolver/remote-resolver';
|
||||||
import dataOperator from '../store/operators';
|
import dataOperator from '../store/operators';
|
||||||
|
|
||||||
@ -23,6 +24,10 @@ const withContext = Base =>
|
|||||||
this.SelectionContext = createSelectionContext(dataOperator);
|
this.SelectionContext = createSelectionContext(dataOperator);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (props.expandRow) {
|
||||||
|
this.RowExpandContext = createRowExpandContext(dataOperator);
|
||||||
|
}
|
||||||
|
|
||||||
if (props.cellEdit && props.cellEdit.createContext) {
|
if (props.cellEdit && props.cellEdit.createContext) {
|
||||||
this.CellEditContext = props.cellEdit.createContext(
|
this.CellEditContext = props.cellEdit.createContext(
|
||||||
_, dataOperator, this.isRemoteCellEdit, this.handleRemoteCellChange);
|
_, dataOperator, this.isRemoteCellEdit, this.handleRemoteCellChange);
|
||||||
@ -52,6 +57,7 @@ const withContext = Base =>
|
|||||||
searchProps,
|
searchProps,
|
||||||
sortProps,
|
sortProps,
|
||||||
paginationProps,
|
paginationProps,
|
||||||
|
expandProps,
|
||||||
selectionProps
|
selectionProps
|
||||||
) => (
|
) => (
|
||||||
<Base
|
<Base
|
||||||
@ -62,6 +68,7 @@ const withContext = Base =>
|
|||||||
{ ...filterProps }
|
{ ...filterProps }
|
||||||
{ ...searchProps }
|
{ ...searchProps }
|
||||||
{ ...paginationProps }
|
{ ...paginationProps }
|
||||||
|
{ ...expandProps }
|
||||||
data={ rootProps.getData(filterProps, searchProps, sortProps, paginationProps) }
|
data={ rootProps.getData(filterProps, searchProps, sortProps, paginationProps) }
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
@ -74,7 +81,8 @@ const withContext = Base =>
|
|||||||
filterProps,
|
filterProps,
|
||||||
searchProps,
|
searchProps,
|
||||||
sortProps,
|
sortProps,
|
||||||
paginationProps
|
paginationProps,
|
||||||
|
expandProps
|
||||||
) => (
|
) => (
|
||||||
<this.SelectionContext.Provider
|
<this.SelectionContext.Provider
|
||||||
{ ...baseProps }
|
{ ...baseProps }
|
||||||
@ -90,6 +98,7 @@ const withContext = Base =>
|
|||||||
searchProps,
|
searchProps,
|
||||||
sortProps,
|
sortProps,
|
||||||
paginationProps,
|
paginationProps,
|
||||||
|
expandProps,
|
||||||
selectionProps
|
selectionProps
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -98,6 +107,37 @@ const withContext = Base =>
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
renderWithRowExpandCtx(base, baseProps) {
|
||||||
|
return (
|
||||||
|
rootProps,
|
||||||
|
cellEditProps,
|
||||||
|
filterProps,
|
||||||
|
searchProps,
|
||||||
|
sortProps,
|
||||||
|
paginationProps
|
||||||
|
) => (
|
||||||
|
<this.RowExpandContext.Provider
|
||||||
|
{ ...baseProps }
|
||||||
|
expandRow={ this.props.expandRow }
|
||||||
|
data={ rootProps.getData(filterProps, searchProps, sortProps, paginationProps) }
|
||||||
|
>
|
||||||
|
<this.RowExpandContext.Consumer>
|
||||||
|
{
|
||||||
|
expandProps => base(
|
||||||
|
rootProps,
|
||||||
|
cellEditProps,
|
||||||
|
filterProps,
|
||||||
|
searchProps,
|
||||||
|
sortProps,
|
||||||
|
paginationProps,
|
||||||
|
expandProps
|
||||||
|
)
|
||||||
|
}
|
||||||
|
</this.RowExpandContext.Consumer>
|
||||||
|
</this.RowExpandContext.Provider>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
renderWithPaginationCtx(base) {
|
renderWithPaginationCtx(base) {
|
||||||
return (
|
return (
|
||||||
rootProps,
|
rootProps,
|
||||||
@ -232,6 +272,10 @@ const withContext = Base =>
|
|||||||
base = this.renderWithSelectionCtx(base, baseProps);
|
base = this.renderWithSelectionCtx(base, baseProps);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.RowExpandContext) {
|
||||||
|
base = this.renderWithRowExpandCtx(base, baseProps);
|
||||||
|
}
|
||||||
|
|
||||||
if (this.PaginationContext) {
|
if (this.PaginationContext) {
|
||||||
base = this.renderWithPaginationCtx(base, baseProps);
|
base = this.renderWithPaginationCtx(base, baseProps);
|
||||||
}
|
}
|
||||||
|
|||||||
62
packages/react-bootstrap-table2/src/contexts/row-expand-context.js
vendored
Normal file
62
packages/react-bootstrap-table2/src/contexts/row-expand-context.js
vendored
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
/* eslint react/prop-types: 0 */
|
||||||
|
import React from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
|
||||||
|
export default (
|
||||||
|
dataOperator
|
||||||
|
) => {
|
||||||
|
const RowExpandContext = React.createContext();
|
||||||
|
|
||||||
|
class RowExpandProvider extends React.Component {
|
||||||
|
static propTypes = {
|
||||||
|
children: PropTypes.node.isRequired,
|
||||||
|
data: PropTypes.array.isRequired,
|
||||||
|
keyField: PropTypes.string.isRequired
|
||||||
|
}
|
||||||
|
|
||||||
|
state = { expanded: this.props.expandRow.expanded || [] };
|
||||||
|
|
||||||
|
componentWillReceiveProps(nextProps) {
|
||||||
|
if (nextProps.expandRow) {
|
||||||
|
this.setState(() => ({
|
||||||
|
expanded: nextProps.expandRow.expanded || this.state.expanded
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
handleRowExpand = (rowKey, expanded, rowIndex, e) => {
|
||||||
|
const { data, keyField, expandRow: { onExpand } } = this.props;
|
||||||
|
|
||||||
|
let currExpanded = [...this.state.expanded];
|
||||||
|
|
||||||
|
if (expanded) {
|
||||||
|
currExpanded.push(rowKey);
|
||||||
|
} else {
|
||||||
|
currExpanded = currExpanded.filter(value => value !== rowKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (onExpand) {
|
||||||
|
const row = dataOperator.getRowByRowId(data, keyField, rowKey);
|
||||||
|
onExpand(row, expanded, rowIndex, e);
|
||||||
|
}
|
||||||
|
this.setState(() => ({ expanded: currExpanded }));
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<RowExpandContext.Provider
|
||||||
|
value={ {
|
||||||
|
expanded: this.state.expanded,
|
||||||
|
onRowExpand: this.handleRowExpand
|
||||||
|
} }
|
||||||
|
>
|
||||||
|
{ this.props.children }
|
||||||
|
</RowExpandContext.Provider>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
Provider: RowExpandProvider,
|
||||||
|
Consumer: RowExpandContext.Consumer
|
||||||
|
};
|
||||||
|
};
|
||||||
@ -1,10 +1,13 @@
|
|||||||
export default ExtendBase =>
|
export default ExtendBase =>
|
||||||
class ColumnResolver extends ExtendBase {
|
class ColumnResolver extends ExtendBase {
|
||||||
visibleColumnSize(includeSelectColumn = true) {
|
visibleColumnSize(includeSelectColumn = true) {
|
||||||
const columnLen = this.props.columns.filter(c => !c.hidden).length;
|
let columnLen = this.props.columns.filter(c => !c.hidden).length;
|
||||||
if (!includeSelectColumn) return columnLen;
|
if (!includeSelectColumn) return columnLen;
|
||||||
if (this.props.selectRow && !this.props.selectRow.hideSelectColumn) {
|
if (this.props.selectRow && !this.props.selectRow.hideSelectColumn) {
|
||||||
return columnLen + 1;
|
columnLen += 1;
|
||||||
|
}
|
||||||
|
if (this.props.expandRow && this.props.expandRow.showExpandColumn) {
|
||||||
|
columnLen += 1;
|
||||||
}
|
}
|
||||||
return columnLen;
|
return columnLen;
|
||||||
}
|
}
|
||||||
|
|||||||
15
packages/react-bootstrap-table2/src/props-resolver/expand-row-resolver.js
vendored
Normal file
15
packages/react-bootstrap-table2/src/props-resolver/expand-row-resolver.js
vendored
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
export default ExtendBase =>
|
||||||
|
class ExpandRowResolver extends ExtendBase {
|
||||||
|
resolveExpandRowProps() {
|
||||||
|
const { expandRow, expanded, onRowExpand } = this.props;
|
||||||
|
if (expandRow) {
|
||||||
|
return {
|
||||||
|
...expandRow,
|
||||||
|
expanded,
|
||||||
|
onRowExpand,
|
||||||
|
nonExpandable: expandRow.nonExpandable || []
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
};
|
||||||
@ -1,9 +1,11 @@
|
|||||||
import ColumnResolver from './column-resolver';
|
import ColumnResolver from './column-resolver';
|
||||||
|
import ExpandRowResolver from './expand-row-resolver';
|
||||||
import Const from '../const';
|
import Const from '../const';
|
||||||
import _ from '../utils';
|
import _ from '../utils';
|
||||||
|
|
||||||
export default ExtendBase =>
|
export default ExtendBase =>
|
||||||
class TableResolver extends ColumnResolver(ExtendBase) {
|
class TableResolver extends
|
||||||
|
ExpandRowResolver(ColumnResolver(ExtendBase)) {
|
||||||
validateProps() {
|
validateProps() {
|
||||||
const { keyField } = this.props;
|
const { keyField } = this.props;
|
||||||
if (!keyField) {
|
if (!keyField) {
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
import _ from './utils';
|
import _ from './utils';
|
||||||
|
import Const from './const';
|
||||||
|
|
||||||
const events = [
|
const events = [
|
||||||
'onClick',
|
'onClick',
|
||||||
@ -30,11 +31,11 @@ export default ExtendBase =>
|
|||||||
selected,
|
selected,
|
||||||
keyField,
|
keyField,
|
||||||
selectable,
|
selectable,
|
||||||
|
expandable,
|
||||||
rowIndex,
|
rowIndex,
|
||||||
selectRow: {
|
expanded,
|
||||||
onRowSelect,
|
expandRow,
|
||||||
clickToEdit
|
selectRow,
|
||||||
},
|
|
||||||
cellEdit: {
|
cellEdit: {
|
||||||
mode,
|
mode,
|
||||||
DBCLICK_TO_CELL_EDIT,
|
DBCLICK_TO_CELL_EDIT,
|
||||||
@ -46,13 +47,16 @@ export default ExtendBase =>
|
|||||||
if (cb) {
|
if (cb) {
|
||||||
cb(e, row, rowIndex);
|
cb(e, row, rowIndex);
|
||||||
}
|
}
|
||||||
if (selectable) {
|
const key = _.get(row, keyField);
|
||||||
const key = _.get(row, keyField);
|
if (expandRow && expandable) {
|
||||||
onRowSelect(key, !selected, rowIndex, e);
|
expandRow.onRowExpand(key, !expanded, rowIndex, e);
|
||||||
|
}
|
||||||
|
if (selectRow.mode !== Const.ROW_SELECT_DISABLED && selectable) {
|
||||||
|
selectRow.onRowSelect(key, !selected, rowIndex, e);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if (mode === DBCLICK_TO_CELL_EDIT && clickToEdit) {
|
if (mode === DBCLICK_TO_CELL_EDIT && selectRow.clickToEdit) {
|
||||||
this.clickNum += 1;
|
this.clickNum += 1;
|
||||||
_.debounce(() => {
|
_.debounce(() => {
|
||||||
if (this.clickNum === 1) {
|
if (this.clickNum === 1) {
|
||||||
@ -68,7 +72,8 @@ export default ExtendBase =>
|
|||||||
|
|
||||||
delegate(attrs = {}) {
|
delegate(attrs = {}) {
|
||||||
const newAttrs = {};
|
const newAttrs = {};
|
||||||
if (this.props.selectRow && this.props.selectRow.clickToSelect) {
|
const { expandRow, selectRow } = this.props;
|
||||||
|
if (expandRow || (selectRow && selectRow.clickToSelect)) {
|
||||||
newAttrs.onClick = this.createClickEventHandler(attrs.onClick);
|
newAttrs.onClick = this.createClickEventHandler(attrs.onClick);
|
||||||
}
|
}
|
||||||
Object.keys(attrs).forEach((attr) => {
|
Object.keys(attrs).forEach((attr) => {
|
||||||
|
|||||||
18
packages/react-bootstrap-table2/src/row-expand/expand-row.js
vendored
Normal file
18
packages/react-bootstrap-table2/src/row-expand/expand-row.js
vendored
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
|
||||||
|
const ExpandRow = ({ children, ...rest }) => (
|
||||||
|
<tr className="expanding-row">
|
||||||
|
<td { ...rest }>{ children }</td>
|
||||||
|
</tr>
|
||||||
|
);
|
||||||
|
|
||||||
|
ExpandRow.propTypes = {
|
||||||
|
children: PropTypes.node
|
||||||
|
};
|
||||||
|
|
||||||
|
ExpandRow.defaultProps = {
|
||||||
|
children: null
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ExpandRow;
|
||||||
@ -30,6 +30,10 @@
|
|||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tr.expanding-row {
|
||||||
|
padding: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
td.react-bootstrap-table-editing-cell {
|
td.react-bootstrap-table-editing-cell {
|
||||||
.animated {
|
.animated {
|
||||||
animation-fill-mode: both;
|
animation-fill-mode: both;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user