mirror of
https://github.com/gosticks/react-bootstrap-table2.git
synced 2025-10-16 11:55:39 +00:00
refactoring pagination context
This commit is contained in:
parent
d3161f02eb
commit
d4be1675db
@ -1,6 +1,23 @@
|
||||
import createContext from './src/context';
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import createBaseContext from './src/state-context';
|
||||
import createDataContext from './src/data-context';
|
||||
|
||||
export default (options = {}) => ({
|
||||
createContext,
|
||||
createContext: createDataContext,
|
||||
options
|
||||
});
|
||||
|
||||
const { Provider, Consumer } = createBaseContext();
|
||||
|
||||
const CustomizableProvider = props => (
|
||||
<Provider { ...props }>
|
||||
<Consumer>{ paginationProps => props.children(paginationProps) }</Consumer>
|
||||
</Provider>
|
||||
);
|
||||
|
||||
CustomizableProvider.propTypes = {
|
||||
children: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
export const PaginationProvider = CustomizableProvider;
|
||||
|
||||
@ -1,182 +0,0 @@
|
||||
/* eslint react/prop-types: 0 */
|
||||
/* eslint react/require-default-props: 0 */
|
||||
/* eslint no-lonely-if: 0 */
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import Const from './const';
|
||||
import { BootstrapContext } from './bootstrap';
|
||||
import Pagination from './pagination';
|
||||
import { getByCurrPage, alignPage } from './page';
|
||||
|
||||
export default (
|
||||
isRemotePagination,
|
||||
handleRemotePageChange
|
||||
) => {
|
||||
const PaginationContext = React.createContext();
|
||||
|
||||
class PaginationProvider extends React.Component {
|
||||
static propTypes = {
|
||||
data: PropTypes.array.isRequired
|
||||
}
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.handleChangePage = this.handleChangePage.bind(this);
|
||||
this.handleChangeSizePerPage = this.handleChangeSizePerPage.bind(this);
|
||||
|
||||
let currPage;
|
||||
let currSizePerPage;
|
||||
const { options } = props.pagination;
|
||||
const sizePerPageList = options.sizePerPageList || Const.SIZE_PER_PAGE_LIST;
|
||||
|
||||
// initialize current page
|
||||
if (typeof options.page !== 'undefined') {
|
||||
currPage = options.page;
|
||||
} else if (typeof options.pageStartIndex !== 'undefined') {
|
||||
currPage = options.pageStartIndex;
|
||||
} else {
|
||||
currPage = Const.PAGE_START_INDEX;
|
||||
}
|
||||
|
||||
// initialize current sizePerPage
|
||||
if (typeof options.sizePerPage !== 'undefined') {
|
||||
currSizePerPage = options.sizePerPage;
|
||||
} else if (typeof sizePerPageList[0] === 'object') {
|
||||
currSizePerPage = sizePerPageList[0].value;
|
||||
} else {
|
||||
currSizePerPage = sizePerPageList[0];
|
||||
}
|
||||
|
||||
this.currPage = currPage;
|
||||
this.currSizePerPage = currSizePerPage;
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
let needNewState = false;
|
||||
let { currPage } = this;
|
||||
const { currSizePerPage } = this;
|
||||
const { onPageChange } = nextProps.pagination.options;
|
||||
|
||||
const pageStartIndex = typeof nextProps.pagination.options.pageStartIndex !== 'undefined' ?
|
||||
nextProps.pagination.options.pageStartIndex : Const.PAGE_START_INDEX;
|
||||
|
||||
// user should align the page when the page is not fit to the data size when remote enable
|
||||
if (!isRemotePagination()) {
|
||||
const newPage = alignPage(nextProps.data, currPage, currSizePerPage, pageStartIndex);
|
||||
if (currPage !== newPage) {
|
||||
currPage = newPage;
|
||||
needNewState = true;
|
||||
}
|
||||
} else {
|
||||
this.currPage = nextProps.pagination.options.page;
|
||||
this.currSizePerPage = nextProps.pagination.options.sizePerPage;
|
||||
}
|
||||
|
||||
if (needNewState) {
|
||||
if (onPageChange) {
|
||||
onPageChange(currPage, currSizePerPage);
|
||||
}
|
||||
this.currPage = currPage;
|
||||
this.currSizePerPage = currSizePerPage;
|
||||
}
|
||||
}
|
||||
|
||||
handleChangePage(currPage) {
|
||||
const { currSizePerPage } = this;
|
||||
const { pagination: { options } } = this.props;
|
||||
|
||||
if (options.onPageChange) {
|
||||
options.onPageChange(currPage, currSizePerPage);
|
||||
}
|
||||
|
||||
this.currPage = currPage;
|
||||
|
||||
if (isRemotePagination()) {
|
||||
handleRemotePageChange(currPage, currSizePerPage);
|
||||
return;
|
||||
}
|
||||
this.forceUpdate();
|
||||
}
|
||||
|
||||
handleChangeSizePerPage(currSizePerPage, currPage) {
|
||||
const { pagination: { options } } = this.props;
|
||||
|
||||
if (options.onSizePerPageChange) {
|
||||
options.onSizePerPageChange(currSizePerPage, currPage);
|
||||
}
|
||||
|
||||
this.currPage = currPage;
|
||||
this.currSizePerPage = currSizePerPage;
|
||||
|
||||
if (isRemotePagination()) {
|
||||
handleRemotePageChange(currPage, currSizePerPage);
|
||||
return;
|
||||
}
|
||||
this.forceUpdate();
|
||||
}
|
||||
|
||||
render() {
|
||||
let { data } = this.props;
|
||||
const { pagination: { options }, bootstrap4 } = this.props;
|
||||
const { currPage, currSizePerPage } = this;
|
||||
const withFirstAndLast = typeof options.withFirstAndLast === 'undefined' ?
|
||||
Const.With_FIRST_AND_LAST : options.withFirstAndLast;
|
||||
const alwaysShowAllBtns = typeof options.alwaysShowAllBtns === 'undefined' ?
|
||||
Const.SHOW_ALL_PAGE_BTNS : options.alwaysShowAllBtns;
|
||||
const hideSizePerPage = typeof options.hideSizePerPage === 'undefined' ?
|
||||
Const.HIDE_SIZE_PER_PAGE : options.hideSizePerPage;
|
||||
const hidePageListOnlyOnePage = typeof options.hidePageListOnlyOnePage === 'undefined' ?
|
||||
Const.HIDE_PAGE_LIST_ONLY_ONE_PAGE : options.hidePageListOnlyOnePage;
|
||||
const pageStartIndex = typeof options.pageStartIndex === 'undefined' ?
|
||||
Const.PAGE_START_INDEX : options.pageStartIndex;
|
||||
|
||||
data = isRemotePagination() ?
|
||||
data :
|
||||
getByCurrPage(
|
||||
data,
|
||||
currPage,
|
||||
currSizePerPage,
|
||||
pageStartIndex
|
||||
);
|
||||
|
||||
return (
|
||||
<PaginationContext.Provider value={ { data } }>
|
||||
{ this.props.children }
|
||||
<BootstrapContext.Provider value={ { bootstrap4 } }>
|
||||
<Pagination
|
||||
key="pagination"
|
||||
dataSize={ options.totalSize || this.props.data.length }
|
||||
currPage={ currPage }
|
||||
currSizePerPage={ currSizePerPage }
|
||||
onPageChange={ this.handleChangePage }
|
||||
onSizePerPageChange={ this.handleChangeSizePerPage }
|
||||
sizePerPageList={ options.sizePerPageList || Const.SIZE_PER_PAGE_LIST }
|
||||
paginationSize={ options.paginationSize || Const.PAGINATION_SIZE }
|
||||
pageStartIndex={ pageStartIndex }
|
||||
withFirstAndLast={ withFirstAndLast }
|
||||
alwaysShowAllBtns={ alwaysShowAllBtns }
|
||||
hideSizePerPage={ hideSizePerPage }
|
||||
hidePageListOnlyOnePage={ hidePageListOnlyOnePage }
|
||||
showTotal={ options.showTotal }
|
||||
paginationTotalRenderer={ options.paginationTotalRenderer }
|
||||
firstPageText={ options.firstPageText || Const.FIRST_PAGE_TEXT }
|
||||
prePageText={ options.prePageText || Const.PRE_PAGE_TEXT }
|
||||
nextPageText={ options.nextPageText || Const.NEXT_PAGE_TEXT }
|
||||
lastPageText={ options.lastPageText || Const.LAST_PAGE_TEXT }
|
||||
prePageTitle={ options.prePageTitle || Const.PRE_PAGE_TITLE }
|
||||
nextPageTitle={ options.nextPageTitle || Const.NEXT_PAGE_TITLE }
|
||||
firstPageTitle={ options.firstPageTitle || Const.FIRST_PAGE_TITLE }
|
||||
lastPageTitle={ options.lastPageTitle || Const.LAST_PAGE_TITLE }
|
||||
/>
|
||||
</BootstrapContext.Provider>
|
||||
</PaginationContext.Provider>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
Provider: PaginationProvider,
|
||||
Consumer: PaginationContext.Consumer
|
||||
};
|
||||
};
|
||||
100
packages/react-bootstrap-table2-paginator/src/data-context.js
vendored
Normal file
100
packages/react-bootstrap-table2-paginator/src/data-context.js
vendored
Normal file
@ -0,0 +1,100 @@
|
||||
/* eslint react/prop-types: 0 */
|
||||
/* eslint react/require-default-props: 0 */
|
||||
/* eslint no-lonely-if: 0 */
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import Const from './const';
|
||||
import { BootstrapContext } from './bootstrap';
|
||||
import Pagination from './pagination';
|
||||
import { getByCurrPage, alignPage } from './page';
|
||||
import createBaseContext from './state-context';
|
||||
|
||||
const { Provider } = createBaseContext();
|
||||
|
||||
const PaginationDataContext = React.createContext();
|
||||
|
||||
class PaginationDataProvider extends Provider {
|
||||
static propTypes = {
|
||||
data: PropTypes.array.isRequired,
|
||||
remoteEmitter: PropTypes.object.isRequired,
|
||||
isRemotePagination: PropTypes.func.isRequired
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
super.componentWillReceiveProps(nextProps);
|
||||
const { currSizePerPage } = this;
|
||||
const { custom, onPageChange } = nextProps.pagination.options;
|
||||
|
||||
const pageStartIndex = typeof nextProps.pagination.options.pageStartIndex !== 'undefined' ?
|
||||
nextProps.pagination.options.pageStartIndex : Const.PAGE_START_INDEX;
|
||||
|
||||
// user should align the page when the page is not fit to the data size when remote enable
|
||||
if (!this.isRemotePagination() && !custom) {
|
||||
const newPage = alignPage(
|
||||
nextProps.data.length, this.currPage, currSizePerPage, pageStartIndex);
|
||||
|
||||
if (this.currPage !== newPage) {
|
||||
if (onPageChange) {
|
||||
onPageChange(newPage, currSizePerPage);
|
||||
}
|
||||
this.currPage = newPage;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
isRemotePagination = () => this.props.isRemotePagination();
|
||||
|
||||
renderDefaultPagination = () => {
|
||||
if (!this.props.pagination.options.custom) {
|
||||
const {
|
||||
bootstrap4,
|
||||
page: currPage,
|
||||
sizePerPage: currSizePerPage,
|
||||
dataSize,
|
||||
...rest
|
||||
} = this.getPaginationProps();
|
||||
return (
|
||||
<BootstrapContext.Provider value={ { bootstrap4 } }>
|
||||
<Pagination
|
||||
{ ...rest }
|
||||
key="pagination"
|
||||
dataSize={ dataSize || this.props.data.length }
|
||||
currPage={ currPage }
|
||||
currSizePerPage={ currSizePerPage }
|
||||
/>
|
||||
</BootstrapContext.Provider>
|
||||
);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
render() {
|
||||
let { data } = this.props;
|
||||
const { pagination: { options } } = this.props;
|
||||
const { currPage, currSizePerPage } = this;
|
||||
const pageStartIndex = typeof options.pageStartIndex === 'undefined' ?
|
||||
Const.PAGE_START_INDEX : options.pageStartIndex;
|
||||
|
||||
data = this.isRemotePagination() ?
|
||||
data :
|
||||
getByCurrPage(
|
||||
data,
|
||||
currPage,
|
||||
currSizePerPage,
|
||||
pageStartIndex
|
||||
);
|
||||
|
||||
return (
|
||||
<PaginationDataContext.Provider value={ { data, setRemoteEmitter: this.setRemoteEmitter } }>
|
||||
{ this.props.children }
|
||||
{ this.renderDefaultPagination() }
|
||||
</PaginationDataContext.Provider>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default () => ({
|
||||
Provider: PaginationDataProvider,
|
||||
Consumer: PaginationDataContext.Consumer
|
||||
});
|
||||
@ -18,13 +18,11 @@ const startIndex = (
|
||||
) => end - (sizePerPage - 1);
|
||||
|
||||
export const alignPage = (
|
||||
data,
|
||||
dataSize,
|
||||
page,
|
||||
sizePerPage,
|
||||
pageStartIndex
|
||||
) => {
|
||||
const dataSize = data.length;
|
||||
|
||||
if (page < pageStartIndex || page > (Math.floor(dataSize / sizePerPage) + pageStartIndex)) {
|
||||
return pageStartIndex;
|
||||
}
|
||||
|
||||
163
packages/react-bootstrap-table2-paginator/src/state-context.js
vendored
Normal file
163
packages/react-bootstrap-table2-paginator/src/state-context.js
vendored
Normal file
@ -0,0 +1,163 @@
|
||||
/* eslint react/prop-types: 0 */
|
||||
/* eslint react/require-default-props: 0 */
|
||||
/* eslint no-lonely-if: 0 */
|
||||
import React from 'react';
|
||||
import Const from './const';
|
||||
|
||||
const StateContext = React.createContext();
|
||||
|
||||
class StateProvider extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.handleChangePage = this.handleChangePage.bind(this);
|
||||
this.handleChangeSizePerPage = this.handleChangeSizePerPage.bind(this);
|
||||
|
||||
let currPage;
|
||||
let currSizePerPage;
|
||||
const { options } = props.pagination;
|
||||
const sizePerPageList = options.sizePerPageList || Const.SIZE_PER_PAGE_LIST;
|
||||
|
||||
// initialize current page
|
||||
if (typeof options.page !== 'undefined') {
|
||||
currPage = options.page;
|
||||
} else if (typeof options.pageStartIndex !== 'undefined') {
|
||||
currPage = options.pageStartIndex;
|
||||
} else {
|
||||
currPage = Const.PAGE_START_INDEX;
|
||||
}
|
||||
|
||||
// initialize current sizePerPage
|
||||
if (typeof options.sizePerPage !== 'undefined') {
|
||||
currSizePerPage = options.sizePerPage;
|
||||
} else if (typeof sizePerPageList[0] === 'object') {
|
||||
currSizePerPage = sizePerPageList[0].value;
|
||||
} else {
|
||||
currSizePerPage = sizePerPageList[0];
|
||||
}
|
||||
|
||||
this.currPage = currPage;
|
||||
this.currSizePerPage = currSizePerPage;
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
const { custom } = nextProps.pagination.options;
|
||||
|
||||
// user should align the page when the page is not fit to the data size when remote enable
|
||||
if (this.isRemotePagination() || custom) {
|
||||
this.currPage = nextProps.pagination.options.page;
|
||||
this.currSizePerPage = nextProps.pagination.options.sizePerPage;
|
||||
}
|
||||
}
|
||||
|
||||
getPaginationProps = () => {
|
||||
const { pagination: { options }, bootstrap4 } = this.props;
|
||||
const { currPage, currSizePerPage } = this;
|
||||
const withFirstAndLast = typeof options.withFirstAndLast === 'undefined' ?
|
||||
Const.With_FIRST_AND_LAST : options.withFirstAndLast;
|
||||
const alwaysShowAllBtns = typeof options.alwaysShowAllBtns === 'undefined' ?
|
||||
Const.SHOW_ALL_PAGE_BTNS : options.alwaysShowAllBtns;
|
||||
const hideSizePerPage = typeof options.hideSizePerPage === 'undefined' ?
|
||||
Const.HIDE_SIZE_PER_PAGE : options.hideSizePerPage;
|
||||
const hidePageListOnlyOnePage = typeof options.hidePageListOnlyOnePage === 'undefined' ?
|
||||
Const.HIDE_PAGE_LIST_ONLY_ONE_PAGE : options.hidePageListOnlyOnePage;
|
||||
const pageStartIndex = typeof options.pageStartIndex === 'undefined' ?
|
||||
Const.PAGE_START_INDEX : options.pageStartIndex;
|
||||
return {
|
||||
...options,
|
||||
bootstrap4,
|
||||
page: currPage,
|
||||
sizePerPage: currSizePerPage,
|
||||
pageStartIndex,
|
||||
hidePageListOnlyOnePage,
|
||||
hideSizePerPage,
|
||||
alwaysShowAllBtns,
|
||||
withFirstAndLast,
|
||||
dataSize: options.totalSize,
|
||||
sizePerPageList: options.sizePerPageList || Const.SIZE_PER_PAGE_LIST,
|
||||
paginationSize: options.paginationSize || Const.PAGINATION_SIZE,
|
||||
showTotal: options.showTotal,
|
||||
paginationTotalRenderer: options.paginationTotalRenderer,
|
||||
firstPageText: options.firstPageText || Const.FIRST_PAGE_TEXT,
|
||||
prePageText: options.prePageText || Const.PRE_PAGE_TEXT,
|
||||
nextPageText: options.nextPageText || Const.NEXT_PAGE_TEXT,
|
||||
lastPageText: options.lastPageText || Const.LAST_PAGE_TEXT,
|
||||
prePageTitle: options.prePageTitle || Const.PRE_PAGE_TITLE,
|
||||
nextPageTitle: options.nextPageTitle || Const.NEXT_PAGE_TITLE,
|
||||
firstPageTitle: options.firstPageTitle || Const.FIRST_PAGE_TITLE,
|
||||
lastPageTitle: options.lastPageTitle || Const.LAST_PAGE_TITLE,
|
||||
onPageChange: this.handleChangePage,
|
||||
onSizePerPageChange: this.handleChangeSizePerPage
|
||||
};
|
||||
}
|
||||
|
||||
setPaginationRemoteEmitter = (remoteEmitter) => {
|
||||
this.remoteEmitter = remoteEmitter;
|
||||
}
|
||||
|
||||
isRemotePagination = () => {
|
||||
const e = {};
|
||||
this.remoteEmitter.emit('isRemotePagination', e);
|
||||
return e.result;
|
||||
};
|
||||
|
||||
handleChangePage(currPage) {
|
||||
const { currSizePerPage } = this;
|
||||
const { pagination: { options } } = this.props;
|
||||
|
||||
if (options.onPageChange) {
|
||||
options.onPageChange(currPage, currSizePerPage);
|
||||
}
|
||||
|
||||
this.currPage = currPage;
|
||||
|
||||
if (this.isRemotePagination()) {
|
||||
this.remoteEmitter.emit('paginationChange', currPage, currSizePerPage);
|
||||
return;
|
||||
}
|
||||
this.forceUpdate();
|
||||
}
|
||||
|
||||
handleChangeSizePerPage(currSizePerPage, currPage) {
|
||||
const { pagination: { options } } = this.props;
|
||||
|
||||
if (options.onSizePerPageChange) {
|
||||
options.onSizePerPageChange(currSizePerPage, currPage);
|
||||
}
|
||||
|
||||
this.currPage = currPage;
|
||||
this.currSizePerPage = currSizePerPage;
|
||||
|
||||
if (this.isRemotePagination()) {
|
||||
this.remoteEmitter.emit('paginationChange', currPage, currSizePerPage);
|
||||
return;
|
||||
}
|
||||
this.forceUpdate();
|
||||
}
|
||||
|
||||
render() {
|
||||
const paginationProps = this.getPaginationProps();
|
||||
const pagination = {
|
||||
...this.props.pagination,
|
||||
options: paginationProps
|
||||
};
|
||||
|
||||
return (
|
||||
<StateContext.Provider
|
||||
value={ {
|
||||
paginationProps,
|
||||
paginationBaseProps: {
|
||||
pagination,
|
||||
setPaginationRemoteEmitter: this.setPaginationRemoteEmitter
|
||||
}
|
||||
} }
|
||||
>
|
||||
{ this.props.children }
|
||||
</StateContext.Provider>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default () => ({
|
||||
Provider: StateProvider,
|
||||
Consumer: StateContext.Consumer
|
||||
});
|
||||
@ -40,8 +40,7 @@ const withContext = Base =>
|
||||
}
|
||||
|
||||
if (props.pagination) {
|
||||
this.PaginationContext = props.pagination.createContext(
|
||||
this.isRemotePagination, this.handleRemotePageChange);
|
||||
this.PaginationContext = props.pagination.createContext();
|
||||
}
|
||||
|
||||
if (props.search && props.search.searchContext) {
|
||||
@ -52,6 +51,10 @@ const withContext = Base =>
|
||||
if (props.setDependencyModules) {
|
||||
props.setDependencyModules(_);
|
||||
}
|
||||
|
||||
if (props.setPaginationRemoteEmitter) {
|
||||
props.setPaginationRemoteEmitter(this.remoteEmitter);
|
||||
}
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
@ -150,6 +153,8 @@ const withContext = Base =>
|
||||
pagination={ this.props.pagination }
|
||||
data={ rootProps.getData(filterProps, searchProps, sortProps) }
|
||||
bootstrap4={ this.props.bootstrap4 }
|
||||
isRemotePagination={ this.isRemotePagination }
|
||||
remoteEmitter={ this.remoteEmitter }
|
||||
>
|
||||
<this.PaginationContext.Consumer>
|
||||
{
|
||||
|
||||
@ -1,7 +1,15 @@
|
||||
import EventEmitter from 'events';
|
||||
import _ from '../utils';
|
||||
|
||||
export default ExtendBase =>
|
||||
class RemoteResolver extends ExtendBase {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.remoteEmitter = new EventEmitter();
|
||||
this.remoteEmitter.on('paginationChange', this.handleRemotePageChange);
|
||||
this.remoteEmitter.on('isRemotePagination', this.isRemotePagination);
|
||||
}
|
||||
|
||||
getNewestState = (state = {}) => {
|
||||
let sortOrder;
|
||||
let sortField;
|
||||
@ -47,9 +55,10 @@ export default ExtendBase =>
|
||||
return remote === true || (_.isObject(remote) && remote.search) || this.isRemotePagination();
|
||||
}
|
||||
|
||||
isRemotePagination = () => {
|
||||
isRemotePagination = (e = {}) => {
|
||||
const { remote } = this.props;
|
||||
return remote === true || (_.isObject(remote) && remote.pagination);
|
||||
e.result = (remote === true || (_.isObject(remote) && remote.pagination));
|
||||
return e.result;
|
||||
}
|
||||
|
||||
isRemoteFiltering = () => {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user