refactoring cell edit consumer

This commit is contained in:
AllenFang 2018-08-20 20:31:22 +08:00
parent 2da6c8c622
commit c5c5a756cd
12 changed files with 181 additions and 123 deletions

View File

@ -1,16 +1,18 @@
import createContext from './src/context'; import createContext from './src/context';
import editingCellFactory from './src/editing-cell'; import bindCellLevelCellEdit from './src/cell-binder';
import bindRowLevelCellEdit from './src/row-binder';
import createEditingCell from './src/editing-cell-binder';
import { import {
EDITTYPE, EDITTYPE,
CLICK_TO_CELL_EDIT,
DBCLICK_TO_CELL_EDIT, DBCLICK_TO_CELL_EDIT,
DELAY_FOR_DBCLICK DELAY_FOR_DBCLICK
} from './src/const'; } from './src/const';
export default (options = {}) => ({ export default (options = {}) => ({
createContext, createContext,
editingCellFactory, createEditingCell,
CLICK_TO_CELL_EDIT, bindCellLevelCellEdit,
bindRowLevelCellEdit,
DBCLICK_TO_CELL_EDIT, DBCLICK_TO_CELL_EDIT,
DELAY_FOR_DBCLICK, DELAY_FOR_DBCLICK,
options options

View File

@ -0,0 +1,38 @@
/* eslint react/prop-types: 0 */
import React from 'react';
import { CLICK_TO_CELL_EDIT, DBCLICK_TO_CELL_EDIT } from './const';
import { Consumer } from './context';
export default (Component, keyField, _) => {
const renderWithCellEdit = (props, cellEdit) => {
const content = _.get(props.row, props.column.dataField);
const editableRow = props.editable;
let editable = _.isDefined(props.column.editable) ? props.column.editable : true;
if (props.column.dataField === keyField || !editableRow) editable = false;
if (_.isFunction(props.column.editable)) {
editable = props.column.editable(
content,
props.row,
props.rowIndex,
props.columnIndex
);
}
return (
<Component
{ ...props }
onStart={ cellEdit.onStart }
editable={ editable }
clickToEdit={ cellEdit.mode === CLICK_TO_CELL_EDIT }
dbclickToEdit={ cellEdit.mode === DBCLICK_TO_CELL_EDIT }
/>
);
};
return props => (
<Consumer>
{ cellEdit => renderWithCellEdit(props, cellEdit) }
</Consumer>
);
};

View File

@ -4,15 +4,14 @@ import React from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { CLICK_TO_CELL_EDIT, DBCLICK_TO_CELL_EDIT } from './const'; import { CLICK_TO_CELL_EDIT, DBCLICK_TO_CELL_EDIT } from './const';
const CellEditContext = React.createContext();
export default ( export default (
_, _,
dataOperator, dataOperator,
isRemoteCellEdit, isRemoteCellEdit,
handleCellChange handleCellChange
) => { ) => {
let EditingCell;
const CellEditContext = React.createContext();
class CellEditProvider extends React.Component { class CellEditProvider extends React.Component {
static propTypes = { static propTypes = {
data: PropTypes.array.isRequired, data: PropTypes.array.isRequired,
@ -32,7 +31,6 @@ export default (
constructor(props) { constructor(props) {
super(props); super(props);
EditingCell = props.cellEdit.editingCellFactory(_, props.cellEdit.options.onStartEdit);
this.startEditing = this.startEditing.bind(this); this.startEditing = this.startEditing.bind(this);
this.escapeEditing = this.escapeEditing.bind(this); this.escapeEditing = this.escapeEditing.bind(this);
this.completeEditing = this.completeEditing.bind(this); this.completeEditing = this.completeEditing.bind(this);
@ -102,7 +100,6 @@ export default (
const { const {
cellEdit: { cellEdit: {
options: { nonEditableRows, errorMessage, ...optionsRest }, options: { nonEditableRows, errorMessage, ...optionsRest },
editingCellFactory,
createContext, createContext,
...cellEditRest ...cellEditRest
} }
@ -112,7 +109,6 @@ export default (
...optionsRest, ...optionsRest,
...cellEditRest, ...cellEditRest,
...this.state, ...this.state,
EditingCell,
nonEditableRows: _.isDefined(nonEditableRows) ? nonEditableRows() : [], nonEditableRows: _.isDefined(nonEditableRows) ? nonEditableRows() : [],
onStart: this.startEditing, onStart: this.startEditing,
onEscape: this.escapeEditing, onEscape: this.escapeEditing,
@ -121,7 +117,7 @@ export default (
return ( return (
<CellEditContext.Provider <CellEditContext.Provider
value={ { cellEdit: newCellEdit } } value={ { ...newCellEdit } }
> >
{ this.props.children } { this.props.children }
</CellEditContext.Provider> </CellEditContext.Provider>
@ -129,7 +125,8 @@ export default (
} }
} }
return { return {
Provider: CellEditProvider, Provider: CellEditProvider
Consumer: CellEditContext.Consumer
}; };
}; };
export const Consumer = CellEditContext.Consumer;

View File

@ -0,0 +1,43 @@
/* eslint react/prop-types: 0 */
import React from 'react';
import { Consumer } from './context';
import createEditingCell from './editing-cell';
export default (_) => {
const renderWithEditingCell = (props, cellEdit) => {
const content = _.get(props.row, props.column.dataField);
let editCellstyle = props.column.editCellStyle || {};
let editCellclasses = props.column.editCellClasses;
if (_.isFunction(props.column.editCellStyle)) {
editCellstyle = props.column.editCellStyle(
content,
props.row,
props.rowIndex,
props.columnIndex
);
}
if (_.isFunction(props.column.editCellClasses)) {
editCellclasses = props.column.editCellClasses(
content,
props.row,
props.rowIndex,
props.columnIndex)
;
}
const EditingCell = createEditingCell(_);
return (
<EditingCell
{ ...props }
className={ editCellclasses }
style={ editCellstyle }
{ ...cellEdit }
/>
);
};
return props => (
<Consumer>
{ cellEdit => renderWithEditingCell(props, cellEdit) }
</Consumer>
);
};

View File

@ -0,0 +1,35 @@
/* eslint react/prop-types: 0 */
import React from 'react';
import { DELAY_FOR_DBCLICK, DBCLICK_TO_CELL_EDIT } from './const';
import { Consumer } from './context';
export default (Component, selectRowEnabled) => {
const renderWithCellEdit = (props, cellEdit) => {
const key = props.value;
const editableRow = !(
cellEdit.nonEditableRows.length > 0 &&
cellEdit.nonEditableRows.indexOf(key) > -1
);
const attrs = {};
if (selectRowEnabled && cellEdit.mode === DBCLICK_TO_CELL_EDIT) {
attrs.DELAY_FOR_DBCLICK = DELAY_FOR_DBCLICK;
}
return (
<Component
{ ...props }
{ ...attrs }
editingRowIdx={ cellEdit.ridx }
editingColIdx={ cellEdit.cidx }
editable={ editableRow }
/>
);
};
return props => (
<Consumer>
{ cellEdit => renderWithCellEdit(props, cellEdit) }
</Consumer>
);
};

View File

@ -6,6 +6,7 @@ import PropTypes from 'prop-types';
import _ from './utils'; import _ from './utils';
import Row from './row'; import Row from './row';
import Cell from './cell';
import RowAggregator from './row-aggregator'; import RowAggregator from './row-aggregator';
import RowSection from './row-section'; import RowSection from './row-section';
import Const from './const'; import Const from './const';
@ -38,55 +39,49 @@ const Body = (props) => {
content = <RowSection content={ indication } colSpan={ visibleColumnSize } />; content = <RowSection content={ indication } colSpan={ visibleColumnSize } />;
} else { } else {
let RowComponent = Row; let RowComponent = Row;
const nonEditableRows = cellEdit.nonEditableRows || [];
const selectRowEnabled = selectRow.mode !== Const.ROW_SELECT_DISABLED; const selectRowEnabled = selectRow.mode !== Const.ROW_SELECT_DISABLED;
const expandRowEnabled = !!expandRow.renderer; const expandRowEnabled = !!expandRow.renderer;
const additionalRowProps = {};
if (expandRowEnabled) { if (expandRowEnabled) {
RowComponent = bindExpansion(RowAggregator, visibleColumnSize); RowComponent = bindExpansion(RowAggregator, visibleColumnSize);
} }
if (selectRowEnabled) { if (selectRowEnabled) {
RowComponent = bindSelection(expandRowEnabled ? RowComponent : RowAggregator); RowComponent = bindSelection(expandRowEnabled ? RowComponent : RowAggregator);
} }
if (cellEdit.createContext) {
const CellComponent = cellEdit.bindCellLevelCellEdit(Cell, keyField, _);
const EditingCell = cellEdit.createEditingCell(_, cellEdit.options.onStartEdit);
RowComponent = cellEdit.bindRowLevelCellEdit(RowComponent, selectRowEnabled);
additionalRowProps.CellComponent = CellComponent;
additionalRowProps.EditingCellComponent = EditingCell;
}
if (selectRowEnabled || expandRowEnabled) {
additionalRowProps.expandRow = expandRow;
additionalRowProps.selectRow = selectRow;
}
content = data.map((row, index) => { content = data.map((row, index) => {
const key = _.get(row, keyField); const key = _.get(row, keyField);
const editable = !(nonEditableRows.length > 0 && nonEditableRows.indexOf(key) > -1); const baseRowProps = {
key,
row,
columns,
keyField,
cellEdit,
value: key,
rowIndex: index,
attrs: rowEvents || {},
...additionalRowProps
};
const attrs = rowEvents || {}; baseRowProps.style = _.isFunction(rowStyle) ? rowStyle(row, index) : rowStyle;
const style = _.isFunction(rowStyle) ? rowStyle(row, index) : rowStyle; baseRowProps.className = (_.isFunction(rowClasses) ? rowClasses(row, index) : rowClasses);
const classes = (_.isFunction(rowClasses) ? rowClasses(row, index) : rowClasses);
// refine later return <RowComponent { ...baseRowProps } />;
const result =
selectRowEnabled || expandRowEnabled ?
(<RowComponent
key={ key }
row={ row }
keyField={ keyField }
rowIndex={ index }
columns={ columns }
style={ style }
className={ classes }
attrs={ attrs }
cellEdit={ cellEdit }
selectRow={ selectRow }
expandRow={ expandRow }
/>) :
(<RowComponent
key={ key }
row={ row }
keyField={ keyField }
rowIndex={ index }
columns={ columns }
cellEdit={ cellEdit }
editable={ editable }
style={ style }
className={ classes }
attrs={ attrs }
/>);
return result;
}); });
} }

View File

@ -56,7 +56,8 @@ class BootstrapTable extends PropsBaseResolver(Component) {
wrapperClasses, wrapperClasses,
rowEvents, rowEvents,
selectRow, selectRow,
expandRow expandRow,
cellEdit
} = this.props; } = this.props;
const tableWrapperClass = cs('react-bootstrap-table', wrapperClasses); const tableWrapperClass = cs('react-bootstrap-table', wrapperClasses);
@ -92,7 +93,7 @@ class BootstrapTable extends PropsBaseResolver(Component) {
isEmpty={ this.isEmpty() } isEmpty={ this.isEmpty() }
visibleColumnSize={ this.visibleColumnSize() } visibleColumnSize={ this.visibleColumnSize() }
noDataIndication={ noDataIndication } noDataIndication={ noDataIndication }
cellEdit={ this.props.cellEdit || {} } cellEdit={ cellEdit }
selectRow={ selectRow } selectRow={ selectRow }
expandRow={ expandRow } expandRow={ expandRow }
rowStyle={ rowStyle } rowStyle={ rowStyle }
@ -195,6 +196,10 @@ BootstrapTable.defaultProps = {
renderer: undefined, renderer: undefined,
expanded: [], expanded: [],
nonExpandable: [] nonExpandable: []
},
cellEdit: {
mode: null,
nonEditableRows: []
} }
}; };

View File

@ -57,7 +57,6 @@ const withContext = Base =>
renderBase() { renderBase() {
return ( return (
rootProps, rootProps,
cellEditProps,
filterProps, filterProps,
searchProps, searchProps,
sortProps, sortProps,
@ -66,7 +65,6 @@ const withContext = Base =>
<Base <Base
{ ...this.props } { ...this.props }
{ ...sortProps } { ...sortProps }
{ ...cellEditProps }
{ ...filterProps } { ...filterProps }
{ ...searchProps } { ...searchProps }
{ ...paginationProps } { ...paginationProps }
@ -78,7 +76,6 @@ const withContext = Base =>
renderWithSelectionCtx(base, baseProps) { renderWithSelectionCtx(base, baseProps) {
return ( return (
rootProps, rootProps,
cellEditProps,
filterProps, filterProps,
searchProps, searchProps,
sortProps, sortProps,
@ -92,7 +89,6 @@ const withContext = Base =>
{ {
base( base(
rootProps, rootProps,
cellEditProps,
filterProps, filterProps,
searchProps, searchProps,
sortProps, sortProps,
@ -106,7 +102,6 @@ const withContext = Base =>
renderWithRowExpandCtx(base, baseProps) { renderWithRowExpandCtx(base, baseProps) {
return ( return (
rootProps, rootProps,
cellEditProps,
filterProps, filterProps,
searchProps, searchProps,
sortProps, sortProps,
@ -120,7 +115,6 @@ const withContext = Base =>
{ {
base( base(
rootProps, rootProps,
cellEditProps,
filterProps, filterProps,
searchProps, searchProps,
sortProps, sortProps,
@ -134,7 +128,6 @@ const withContext = Base =>
renderWithPaginationCtx(base) { renderWithPaginationCtx(base) {
return ( return (
rootProps, rootProps,
cellEditProps,
filterProps, filterProps,
searchProps, searchProps,
sortProps sortProps
@ -149,7 +142,6 @@ const withContext = Base =>
{ {
paginationProps => base( paginationProps => base(
rootProps, rootProps,
cellEditProps,
filterProps, filterProps,
searchProps, searchProps,
sortProps, sortProps,
@ -164,7 +156,6 @@ const withContext = Base =>
renderWithSortCtx(base, baseProps) { renderWithSortCtx(base, baseProps) {
return ( return (
rootProps, rootProps,
cellEditProps,
filterProps, filterProps,
searchProps searchProps
) => ( ) => (
@ -179,7 +170,6 @@ const withContext = Base =>
{ {
sortProps => base( sortProps => base(
rootProps, rootProps,
cellEditProps,
filterProps, filterProps,
searchProps, searchProps,
sortProps, sortProps,
@ -193,7 +183,6 @@ const withContext = Base =>
renderWithSearchCtx(base, baseProps) { renderWithSearchCtx(base, baseProps) {
return ( return (
rootProps, rootProps,
cellEditProps,
filterProps filterProps
) => ( ) => (
<this.SearchContext.Provider <this.SearchContext.Provider
@ -206,7 +195,6 @@ const withContext = Base =>
{ {
searchProps => base( searchProps => base(
rootProps, rootProps,
cellEditProps,
filterProps, filterProps,
searchProps searchProps
) )
@ -217,10 +205,7 @@ const withContext = Base =>
} }
renderWithFilterCtx(base, baseProps) { renderWithFilterCtx(base, baseProps) {
return ( return rootProps => (
rootProps,
cellEditProps
) => (
<this.FilterContext.Provider <this.FilterContext.Provider
{ ...baseProps } { ...baseProps }
ref={ n => this.filterContext = n } ref={ n => this.filterContext = n }
@ -230,7 +215,6 @@ const withContext = Base =>
{ {
filterProps => base( filterProps => base(
rootProps, rootProps,
cellEditProps,
filterProps filterProps
) )
} }
@ -247,11 +231,7 @@ const withContext = Base =>
cellEdit={ this.props.cellEdit } cellEdit={ this.props.cellEdit }
data={ rootProps.getData() } data={ rootProps.getData() }
> >
<this.CellEditContext.Consumer> { base(rootProps) }
{
cellEditProps => base(rootProps, cellEditProps)
}
</this.CellEditContext.Consumer>
</this.CellEditContext.Provider> </this.CellEditContext.Provider>
); );
} }

View File

@ -33,11 +33,7 @@ export default class RowAggregator extends React.Component {
expanded, expanded,
expandRow, expandRow,
selectRow, selectRow,
cellEdit: {
mode,
DBCLICK_TO_CELL_EDIT,
DELAY_FOR_DBCLICK DELAY_FOR_DBCLICK
}
} = this.props; } = this.props;
const clickFn = () => { const clickFn = () => {
@ -53,7 +49,7 @@ export default class RowAggregator extends React.Component {
} }
}; };
if (mode === DBCLICK_TO_CELL_EDIT && selectRow.clickToEdit) { if (DELAY_FOR_DBCLICK) {
this.clickNum += 1; this.clickNum += 1;
_.debounce(() => { _.debounce(() => {
if (this.clickNum === 1) { if (this.clickNum === 1) {
@ -76,21 +72,18 @@ export default class RowAggregator extends React.Component {
style, style,
className, className,
attrs, attrs,
cellEdit,
selectRow, selectRow,
expandRow, expandRow,
expanded, expanded,
selected, selected,
selectable selectable,
...rest
} = this.props; } = this.props;
const key = _.get(row, keyField); const key = _.get(row, keyField);
const { hideSelectColumn, clickToSelect } = selectRow; const { hideSelectColumn, clickToSelect } = selectRow;
const { showExpandColumn } = expandRow; const { showExpandColumn } = expandRow;
const nonEditableRows = cellEdit.nonEditableRows || [];
const editable = !(nonEditableRows.length > 0 && nonEditableRows.indexOf(key) > -1);
const newAttrs = { ...attrs }; const newAttrs = { ...attrs };
if (clickToSelect || !!expandRow.renderer) { if (clickToSelect || !!expandRow.renderer) {
newAttrs.onClick = this.createClickEventHandler(attrs.onClick); newAttrs.onClick = this.createClickEventHandler(attrs.onClick);
@ -103,11 +96,10 @@ export default class RowAggregator extends React.Component {
keyField={ keyField } keyField={ keyField }
rowIndex={ rowIndex } rowIndex={ rowIndex }
columns={ columns } columns={ columns }
cellEdit={ cellEdit }
editable={ editable }
style={ style } style={ style }
className={ className } className={ className }
attrs={ newAttrs } attrs={ newAttrs }
{ ...rest }
> >
{ {
showExpandColumn ? ( showExpandColumn ? (

View File

@ -1,12 +1,11 @@
/* eslint react/prop-types: 0 */ /* eslint react/prop-types: 0 */
import React from 'react'; import React from 'react';
import _ from '../utils';
import ExpandRow from './expand-row'; import ExpandRow from './expand-row';
import ExpansionContext from '../contexts/row-expand-context'; import ExpansionContext from '../contexts/row-expand-context';
export default (Component, visibleColumnSize) => { export default (Component, visibleColumnSize) => {
const renderWithExpansion = (props, expandRow) => { const renderWithExpansion = (props, expandRow) => {
const key = _.get(props.row, props.keyField); const key = props.value;
const expanded = expandRow.expanded.includes(key); const expanded = expandRow.expanded.includes(key);
const expandable = !expandRow.nonExpandable || !expandRow.nonExpandable.includes(key); const expandable = !expandRow.nonExpandable || !expandRow.nonExpandable.includes(key);

View File

@ -6,7 +6,7 @@ import SelectionContext from '../contexts/selection-context';
export default (Component) => { export default (Component) => {
const renderWithSelection = (props, selectRow) => { const renderWithSelection = (props, selectRow) => {
const key = _.get(props.row, props.keyField); const key = props.value;
const selected = selectRow.selected.includes(key); const selected = selectRow.selected.includes(key);
const selectable = !selectRow.nonSelectable || !selectRow.nonSelectable.includes(key); const selectable = !selectRow.nonSelectable || !selectRow.nonSelectable.includes(key);

View File

@ -12,25 +12,15 @@ class Row extends eventDelegater(Component) {
const { const {
row, row,
columns, columns,
keyField,
rowIndex, rowIndex,
className, className,
style, style,
attrs, attrs,
cellEdit, editable,
editable: editableRow editingRowIdx,
editingColIdx
} = this.props; } = this.props;
const CellComponent = this.props.CellComponent || Cell;
const {
mode,
onStart,
EditingCell,
ridx: editingRowIdx,
cidx: editingColIdx,
CLICK_TO_CELL_EDIT,
DBCLICK_TO_CELL_EDIT,
...rest
} = cellEdit;
const trAttrs = this.delegate(attrs); const trAttrs = this.delegate(attrs);
return ( return (
@ -41,20 +31,8 @@ class Row extends eventDelegater(Component) {
if (!column.hidden) { if (!column.hidden) {
const { dataField } = column; const { dataField } = column;
const content = _.get(row, dataField); const content = _.get(row, dataField);
let editable = _.isDefined(column.editable) ? column.editable : true;
if (dataField === keyField || !editableRow) editable = false;
if (_.isFunction(column.editable)) {
editable = column.editable(content, row, rowIndex, index);
}
if (rowIndex === editingRowIdx && index === editingColIdx) { if (rowIndex === editingRowIdx && index === editingColIdx) {
let editCellstyle = column.editCellStyle || {}; const EditingCell = this.props.EditingCellComponent;
let editCellclasses = column.editCellClasses;
if (_.isFunction(column.editCellStyle)) {
editCellstyle = column.editCellStyle(content, row, rowIndex, index);
}
if (_.isFunction(column.editCellClasses)) {
editCellclasses = column.editCellClasses(content, row, rowIndex, index);
}
return ( return (
<EditingCell <EditingCell
key={ `${content}-${index}` } key={ `${content}-${index}` }
@ -62,9 +40,6 @@ class Row extends eventDelegater(Component) {
rowIndex={ rowIndex } rowIndex={ rowIndex }
column={ column } column={ column }
columnIndex={ index } columnIndex={ index }
className={ editCellclasses }
style={ editCellstyle }
{ ...rest }
/> />
); );
} }
@ -108,16 +83,13 @@ class Row extends eventDelegater(Component) {
if (!_.isEmptyObject(cellStyle)) cellAttrs.style = cellStyle; if (!_.isEmptyObject(cellStyle)) cellAttrs.style = cellStyle;
return ( return (
<Cell <CellComponent
key={ `${content}-${index}` } key={ `${content}-${index}` }
row={ row } row={ row }
editable={ editable }
rowIndex={ rowIndex } rowIndex={ rowIndex }
columnIndex={ index } columnIndex={ index }
column={ column } column={ column }
onStart={ onStart }
editable={ editable }
clickToEdit={ mode === CLICK_TO_CELL_EDIT }
dbclickToEdit={ mode === DBCLICK_TO_CELL_EDIT }
{ ...cellAttrs } { ...cellAttrs }
/> />
); );