implement expand row sketch

This commit is contained in:
AllenFang 2018-06-24 13:12:23 +08:00
parent 6eaffe1993
commit 35b1e37940
10 changed files with 198 additions and 16 deletions

View File

@ -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;
}); });
} }

View File

@ -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]),

View File

@ -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);
} }

View 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
};
};

View File

@ -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;
} }

View 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;
}
};

View File

@ -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) {

View File

@ -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) => {

View 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;

View File

@ -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;