implement celledit context

This commit is contained in:
AllenFang
2018-08-01 20:14:33 +08:00
parent 5307e58813
commit 216bc10142
5 changed files with 122 additions and 78 deletions
+2 -2
View File
@@ -1,4 +1,4 @@
import wrapperFactory from './src/wrapper';
import createContext from './src/context';
import editingCellFactory from './src/editing-cell';
import {
EDITTYPE,
@@ -8,7 +8,7 @@ import {
} from './src/const';
export default (options = {}) => ({
wrapperFactory,
createContext,
editingCellFactory,
CLICK_TO_CELL_EDIT,
DBCLICK_TO_CELL_EDIT,
@@ -1,16 +1,21 @@
/* eslint react/prop-types: 0 */
import React, { Component } from 'react';
/* eslint react/require-default-props: 0 */
import React from 'react';
import PropTypes from 'prop-types';
import { CLICK_TO_CELL_EDIT, DBCLICK_TO_CELL_EDIT } from './const';
export default (
Base,
{ _, remoteResolver }
_,
dataOperator,
isRemoteCellEdit,
handleCellChange
) => {
let EditingCell;
return class CellEditWrapper extends remoteResolver(Component) {
const CellEditContext = React.createContext();
class CellEditProvider extends React.Component {
static propTypes = {
data: PropTypes.array.isRequired,
options: PropTypes.shape({
mode: PropTypes.oneOf([CLICK_TO_CELL_EDIT, DBCLICK_TO_CELL_EDIT]).isRequired,
onErrorMessageDisappear: PropTypes.func,
@@ -19,7 +24,7 @@ export default (
afterSaveCell: PropTypes.func,
nonEditableRows: PropTypes.func,
timeToCloseMessage: PropTypes.number,
errorMessage: PropTypes.string
errorMessage: PropTypes.any
})
}
@@ -33,41 +38,32 @@ export default (
this.state = {
ridx: null,
cidx: null,
message: null,
isDataChanged: false
message: null
};
}
componentWillReceiveProps(nextProps) {
if (nextProps.cellEdit && this.isRemoteCellEdit()) {
if (nextProps.cellEdit && isRemoteCellEdit()) {
if (nextProps.cellEdit.options.errorMessage) {
this.setState(() => ({
isDataChanged: false,
message: nextProps.cellEdit.options.errorMessage
}));
} else {
this.setState(() => ({
isDataChanged: true
}));
this.escapeEditing();
}
} else {
this.setState(() => ({
isDataChanged: false
}));
}
}
handleCellUpdate(row, column, newValue) {
const { keyField, cellEdit, store } = this.props;
const { keyField, cellEdit, data } = this.props;
const { beforeSaveCell, afterSaveCell } = cellEdit.options;
const oldValue = _.get(row, column.dataField);
const rowId = _.get(row, keyField);
if (_.isFunction(beforeSaveCell)) beforeSaveCell(oldValue, newValue, row, column);
if (this.isRemoteCellEdit()) {
this.handleCellChange(rowId, column.dataField, newValue);
if (isRemoteCellEdit()) {
handleCellChange(rowId, column.dataField, newValue);
} else {
store.edit(rowId, column.dataField, newValue);
dataOperator.editCell(data, keyField, rowId, column.dataField, newValue);
if (_.isFunction(afterSaveCell)) afterSaveCell(oldValue, newValue, row, column);
this.completeEditing();
}
@@ -77,8 +73,7 @@ export default (
this.setState(() => ({
ridx: null,
cidx: null,
message: null,
isDataChanged: true
message: null
}));
}
@@ -86,8 +81,7 @@ export default (
const editing = () => {
this.setState(() => ({
ridx,
cidx,
isDataChanged: false
cidx
}));
};
@@ -103,7 +97,6 @@ export default (
}
render() {
const { isDataChanged, ...stateRest } = this.state;
const {
cellEdit: {
options: { nonEditableRows, errorMessage, ...optionsRest },
@@ -111,10 +104,11 @@ export default (
...cellEditRest
}
} = this.props;
const newCellEdit = {
...optionsRest,
...cellEditRest,
...stateRest,
...this.state,
EditingCell,
nonEditableRows: _.isDefined(nonEditableRows) ? nonEditableRows() : [],
onStart: this.startEditing,
@@ -123,13 +117,16 @@ export default (
};
return (
<Base
{ ...this.props }
data={ this.props.store.data }
isDataChanged={ isDataChanged }
cellEdit={ newCellEdit }
/>
<CellEditContext.Provider
value={ { cellEdit: newCellEdit } }
>
{ this.props.children }
</CellEditContext.Provider>
);
}
}
return {
Provider: CellEditProvider,
Consumer: CellEditContext.Consumer
};
};
+77 -37
View File
@@ -1,27 +1,100 @@
/* eslint no-return-assign: 0 */
import React, { Component } from 'react';
import _ from '../utils';
import createDataContext from './data-context';
import createSortContext from './sort-context';
import createSelectionContext from './selection-context';
import remoteResolver from '../props-resolver/remote-resolver';
import dataOperator from '../store/operators';
const withContext = (Base) => {
let DataContext;
let SelectionContext;
let CellEditContext;
let SortContext;
return class BootstrapTableContainer extends remoteResolver(Component) {
constructor(props) {
super(props);
DataContext = createDataContext(this.props.data);
SelectionContext = createSelectionContext();
SortContext = createSortContext(this.isRemoteSort, this.handleSortChange);
DataContext = createDataContext(props.data);
SelectionContext = createSelectionContext(dataOperator);
SortContext = createSortContext(dataOperator, this.isRemoteSort, this.handleSortChange);
if (props.cellEdit && props.cellEdit.createContext) {
CellEditContext = props.cellEdit.createContext(
_, dataOperator, this.isRemoteCellEdit, this.handleCellChange);
}
}
componentWillReceiveProps(nextProps) {
if (!nextProps.cellEdit) {
CellEditContext = null;
}
}
renderBase(baseProps) {
return (rootProps, cellEditProps) => (
<SortContext.Provider
{ ...baseProps }
ref={ n => this.sortContext = n }
defaultSorted={ this.props.defaultSorted }
defaultSortDirection={ this.props.defaultSortDirection }
data={ rootProps.data }
>
<SortContext.Consumer>
{
sortProps => (
<SelectionContext.Provider
{ ...baseProps }
selectRow={ this.props.selectRow }
data={ sortProps.data }
>
<SelectionContext.Consumer>
{
selectionProps => (
<Base
{ ...this.props }
{ ...selectionProps }
{ ...sortProps }
{ ...cellEditProps }
data={ sortProps.data }
/>
)
}
</SelectionContext.Consumer>
</SelectionContext.Provider>
)
}
</SortContext.Consumer>
</SortContext.Provider>
);
}
renderWithCellEdit(base, baseProps) {
return rootProps => (
<CellEditContext.Provider
{ ...baseProps }
cellEdit={ this.props.cellEdit }
data={ rootProps.data }
>
<CellEditContext.Consumer>
{
cellEditprops => base(rootProps, cellEditprops)
}
</CellEditContext.Consumer>
</CellEditContext.Provider>
);
}
render() {
const { keyField, columns } = this.props;
const baseProps = { keyField, columns };
let base = this.renderBase(baseProps);
if (CellEditContext) {
base = this.renderWithCellEdit(base, baseProps);
}
return (
<DataContext.Provider
{ ...baseProps }
@@ -29,40 +102,7 @@ const withContext = (Base) => {
>
<DataContext.Consumer>
{
rootProps => (
<SelectionContext.Provider
{ ...baseProps }
selectRow={ this.props.selectRow }
data={ rootProps.data }
>
<SelectionContext.Consumer>
{
selectionProps => (
<SortContext.Provider
ref={ n => this.sortProvider = n }
{ ...baseProps }
defaultSorted={ this.props.defaultSorted }
defaultSortDirection={ this.props.defaultSortDirection }
data={ rootProps.data }
>
<SortContext.Consumer>
{
sortProps => (
<Base
{ ...this.props }
{ ...selectionProps }
{ ...sortProps }
data={ sortProps.data }
/>
)
}
</SortContext.Consumer>
</SortContext.Provider>
)
}
</SelectionContext.Consumer>
</SelectionContext.Provider>
)
base
}
</DataContext.Consumer>
</DataContext.Provider>
@@ -3,7 +3,7 @@ import _ from '../utils';
export default ExtendBase =>
class RemoteResolver extends ExtendBase {
/* eslint class-methods-use-this: 0 */
getNewestState(state = {}) {
getNewestState = (state = {}) => {
// const store = this.store || this.props.store;
// return {
// page: store.page,
@@ -14,7 +14,14 @@ export default ExtendBase =>
// data: store.getAllData(),
// ...state
// };
return { ...state, data: this.props.data };
return {
sortOrder: this.sortContext.state.sortOrder,
sortField: this.sortContext.state.sortColumn ?
this.sortContext.state.sortColumn.dataField :
null,
...state,
data: this.props.data
};
}
isRemotePagination() {
@@ -32,7 +39,7 @@ export default ExtendBase =>
return remote === true || (_.isObject(remote) && remote.sort) || this.isRemotePagination();
}
isRemoteCellEdit() {
isRemoteCellEdit = () => {
const { remote } = this.props;
return remote === true || (_.isObject(remote) && remote.cellEdit);
}
@@ -54,7 +61,7 @@ export default ExtendBase =>
this.props.onTableChange('sort', this.getNewestState({ sortField, sortOrder }));
}
handleCellChange(rowId, dataField, newValue) {
handleCellChange = (rowId, dataField, newValue) => {
const cellEdit = { rowId, dataField, newValue };
this.props.onTableChange('cellEdit', this.getNewestState({ cellEdit }));
}
+2 -2
View File
@@ -1,7 +1,7 @@
import _ from '../utils';
import { getRowByRowId } from './rows';
export const editCell = (rowId, dataField, newValue) => {
const row = getRowByRowId(this)(rowId);
export const editCell = (data, keyField, rowId, dataField, newValue) => {
const row = getRowByRowId(data, keyField, rowId);
if (row) _.set(row, dataField, newValue);
};