implement expand indicator

This commit is contained in:
AllenFang
2018-07-01 15:20:07 +08:00
parent dbd0f89a3d
commit 4af5b4f6ef
9 changed files with 179 additions and 6 deletions

View File

@@ -72,6 +72,7 @@ class BootstrapTable extends PropsBaseResolver(Component) {
});
const tableCaption = (caption && <Caption>{ caption }</Caption>);
const expandRow = this.resolveExpandRowProps();
return (
<div className={ tableWrapperClass }>
@@ -86,6 +87,7 @@ class BootstrapTable extends PropsBaseResolver(Component) {
onFilter={ this.props.onFilter }
onExternalFilter={ this.props.onExternalFilter }
selectRow={ headerCellSelectionInfo }
expandRow={ expandRow }
/>
<Body
data={ data }
@@ -97,7 +99,7 @@ class BootstrapTable extends PropsBaseResolver(Component) {
cellEdit={ this.props.cellEdit || {} }
selectRow={ cellSelectionInfo }
selectedRowKeys={ selected }
expandRow={ this.resolveExpandRowProps() }
expandRow={ expandRow }
rowStyle={ rowStyle }
rowClasses={ rowClasses }
rowEvents={ rowEvents }
@@ -151,9 +153,12 @@ BootstrapTable.propTypes = {
expanded: PropTypes.array,
nonExpandable: PropTypes.array,
showExpandColumn: PropTypes.bool,
expandColumnRenderer: PropTypes.func
expandColumnRenderer: PropTypes.func,
expandHeaderColumnRenderer: PropTypes.func
}),
onRowExpand: PropTypes.func,
onAllRowExpand: PropTypes.func,
isAnyExpands: PropTypes.func,
rowStyle: PropTypes.oneOfType([PropTypes.object, PropTypes.func]),
rowEvents: PropTypes.object,
rowClasses: PropTypes.oneOfType([PropTypes.string, PropTypes.func]),

View File

@@ -42,12 +42,41 @@ export default (
this.setState(() => ({ expanded: currExpanded }));
}
handleAllRowExpand = (e, expandAll) => {
const {
data,
keyField,
expandRow: {
onExpandAll,
nonExpandable
}
} = this.props;
const { expanded } = this.state;
let currExpanded;
if (expandAll) {
currExpanded = expanded.concat(dataOperator.expandableKeys(data, keyField, nonExpandable));
} else {
currExpanded = expanded.filter(s => typeof data.find(d => d[keyField] === s) === 'undefined');
}
if (onExpandAll) {
onExpandAll(expandAll, dataOperator.getExpandedRows(data, keyField, currExpanded), e);
}
this.setState(() => ({ expanded: currExpanded }));
}
render() {
const { data, keyField } = this.props;
return (
<RowExpandContext.Provider
value={ {
isAnyExpands: dataOperator.isAnyExpands(data, keyField, this.state.expanded),
expanded: this.state.expanded,
onRowExpand: this.handleRowExpand
onRowExpand: this.handleRowExpand,
onAllRowExpand: this.handleAllRowExpand
} }
>
{ this.props.children }

View File

@@ -5,6 +5,7 @@ import Const from './const';
import HeaderCell from './header-cell';
import SelectionHeaderCell from './row-selection/selection-header-cell';
import ExpandHeaderCell from './row-expand/expand-header-cell';
const Header = (props) => {
const { ROW_SELECT_DISABLED } = Const;
@@ -17,12 +18,21 @@ const Header = (props) => {
sortField,
sortOrder,
selectRow,
onExternalFilter
onExternalFilter,
expandRow
} = props;
return (
<thead>
<tr className={ className }>
{
(expandRow && expandRow.showExpandColumn)
? <ExpandHeaderCell
onAllRowExpand={ expandRow.onAllRowExpand }
anyExpands={ expandRow.isAnyExpands }
renderer={ expandRow.expandHeaderColumnRenderer }
/> : null
}
{
(selectRow.mode !== ROW_SELECT_DISABLED && !selectRow.hideSelectColumn)
? <SelectionHeaderCell { ...selectRow } /> : null
@@ -62,7 +72,8 @@ Header.propTypes = {
sortOrder: PropTypes.string,
selectRow: PropTypes.object,
onExternalFilter: PropTypes.func,
className: PropTypes.string
className: PropTypes.string,
expandRow: PropTypes.object
};
export default Header;

View File

@@ -1,12 +1,14 @@
export default ExtendBase =>
class ExpandRowResolver extends ExtendBase {
resolveExpandRowProps() {
const { expandRow, expanded, onRowExpand } = this.props;
const { expandRow, expanded, onRowExpand, onAllRowExpand, isAnyExpands } = this.props;
if (expandRow) {
return {
...expandRow,
expanded,
onRowExpand,
onAllRowExpand,
isAnyExpands,
nonExpandable: expandRow.nonExpandable || []
};
}

View File

@@ -0,0 +1,42 @@
/* eslint
react/require-default-props: 0
jsx-a11y/no-noninteractive-element-interactions: 0
*/
/* eslint no-nested-ternary: 0 */
import React, { Component } from 'react';
import PropTypes from 'prop-types';
export default class ExpandCell extends Component {
static propTypes = {
rowKey: PropTypes.any,
expanded: PropTypes.bool.isRequired,
onRowExpand: PropTypes.func.isRequired,
expandColumnRenderer: PropTypes.func,
rowIndex: PropTypes.number
}
constructor() {
super();
this.handleClick = this.handleClick.bind(this);
}
handleClick(e) {
const { rowKey, expanded, onRowExpand, rowIndex } = this.props;
onRowExpand(rowKey, expanded, rowIndex, e);
}
render() {
const { expanded, expandColumnRenderer } = this.props;
return (
<td onClick={ this.handleClick }>
{
expandColumnRenderer ? expandColumnRenderer({
expanded
}) : (expanded ? '(-)' : '(+)')
}
</td>
);
}
}

View File

@@ -0,0 +1,40 @@
/* eslint react/require-default-props: 0 */
/* eslint no-nested-ternary: 0 */
import React, { Component } from 'react';
import PropTypes from 'prop-types';
export default class SelectionHeaderCell extends Component {
static propTypes = {
anyExpands: PropTypes.bool.isRequired,
onAllRowExpand: PropTypes.func.isRequired,
renderer: PropTypes.func
}
constructor() {
super();
this.handleCheckBoxClick = this.handleCheckBoxClick.bind(this);
}
handleCheckBoxClick(e) {
const { anyExpands, onAllRowExpand } = this.props;
onAllRowExpand(e, !anyExpands);
}
render() {
const { anyExpands, renderer } = this.props;
const attrs = {
onClick: this.handleCheckBoxClick
};
return (
<th data-row-selection { ...attrs }>
{
renderer ?
renderer({ isAnyExpands: anyExpands }) :
(anyExpands ? '(-)' : '(+)')
}
</th>
);
}
}

View File

@@ -6,6 +6,7 @@ import PropTypes from 'prop-types';
import _ from './utils';
import Cell from './cell';
import SelectionCell from './row-selection/selection-cell';
import ExpandCell from './row-expand/expand-cell';
import eventDelegater from './row-event-delegater';
import Const from './const';
@@ -22,6 +23,8 @@ class Row extends eventDelegater(Component) {
cellEdit,
selected,
selectRow,
expanded,
expandRow,
selectable,
editable: editableRow
} = this.props;
@@ -39,10 +42,21 @@ class Row extends eventDelegater(Component) {
const key = _.get(row, keyField);
const { hideSelectColumn } = selectRow;
const { showExpandColumn } = expandRow || {};
const trAttrs = this.delegate(attrs);
return (
<tr style={ style } className={ className } { ...trAttrs }>
{
showExpandColumn ? (
<ExpandCell
{ ...expandRow }
rowKey={ key }
rowIndex={ rowIndex }
expanded={ expanded }
/>
) : null
}
{
(selectRow.mode !== Const.ROW_SELECT_DISABLED && !hideSelectColumn)
? (

View File

@@ -0,0 +1,28 @@
import _ from '../utils';
import { getRowByRowId } from './rows';
export const isAnyExpands = (
data,
keyField,
expanded = []
) => {
for (let i = 0; i < data.length; i += 1) {
const rowKey = _.get(data[i], keyField);
if (typeof expanded.find(x => x === rowKey) !== 'undefined') {
return true;
}
}
return false;
};
export const expandableKeys = (data, keyField, skips = []) => {
if (skips.length === 0) {
return data.map(row => _.get(row, keyField));
}
return data
.filter(row => !skips.includes(_.get(row, keyField)))
.map(row => _.get(row, keyField));
};
export const getExpandedRows = (data, keyField, expanded) =>
expanded.map(k => getRowByRowId(data, keyField, k));

View File

@@ -1,11 +1,13 @@
import * as rows from './rows';
import * as selection from './selection';
import * as expand from './expand';
import * as mutate from './mutate';
import * as sort from './sort';
export default {
...rows,
...selection,
...expand,
...mutate,
...sort
};