From e9f08d278d8e70df8ddbbcd533a8478070cf25de Mon Sep 17 00:00:00 2001 From: AllenFang Date: Sat, 9 Mar 2019 15:52:10 +0800 Subject: [PATCH] fix #826 --- .../pagination-with-dynamic-data.js | 150 ++++++++++++++++++ .../stories/index.js | 2 + .../src/data-context.js | 7 +- .../src/page.js | 14 +- .../src/state-context.js | 3 +- .../test/page.test.js | 132 +++++++++++++-- 6 files changed, 295 insertions(+), 13 deletions(-) create mode 100644 packages/react-bootstrap-table2-example/examples/pagination/pagination-with-dynamic-data.js diff --git a/packages/react-bootstrap-table2-example/examples/pagination/pagination-with-dynamic-data.js b/packages/react-bootstrap-table2-example/examples/pagination/pagination-with-dynamic-data.js new file mode 100644 index 0000000..cdd6f3d --- /dev/null +++ b/packages/react-bootstrap-table2-example/examples/pagination/pagination-with-dynamic-data.js @@ -0,0 +1,150 @@ +import React from 'react'; + +import BootstrapTable from 'react-bootstrap-table-next'; +import paginationFactory from 'react-bootstrap-table2-paginator'; +import Code from 'components/common/code-block'; + +const sourceCode = `\ +import BootstrapTable from 'react-bootstrap-table-next'; +import paginationFactory from 'react-bootstrap-table2-paginator'; + +class BookList extends React.Component { + state = { + books: [ + { id: '1', name: 'Book 1' }, + { id: '2', name: 'Book 2' }, + { id: '3', name: 'Book 3' }, + { id: '4', name: 'Book 4' }, + { id: '5', name: 'Book 5' }, + { id: '6', name: 'Book 6' } + ] + }; + + deleteBookWithId = () => { + const lastOneId = this.state.books.length; + const updatedBooks = this.state.books.filter(m => m.id !== lastOneId.toString()); + this.setState({ books: updatedBooks }); + }; + + addBook = () => { + const lastOneId = this.state.books.length + 1; + this.setState({ books: [...this.state.books, { + id: \`$\{lastOneId}\`, name: \`Book $\{lastOneId}\` + }] }); + } + + render() { + const options = { + // pageStartIndex: 0, + sizePerPage: 5, + hideSizePerPage: true, + hidePageListOnlyOnePage: true + }; + const columns = [ + { + dataField: 'id', + text: 'Product ID', + Cell: row => ( +
+ { row.value } +
+ ) + }, + { + dataField: 'name', + text: 'Product Name' + } + ]; + + return ( + + + + + { sourceCode } + + ); + } +`; + +export default class BookList extends React.Component { + state = { + books: [ + { id: '1', name: 'Book 1' }, + { id: '2', name: 'Book 2' }, + { id: '3', name: 'Book 3' }, + { id: '4', name: 'Book 4' }, + { id: '5', name: 'Book 5' }, + { id: '6', name: 'Book 6' }, + { id: '7', name: 'Book 6' }, + { id: '8', name: 'Book 6' }, + { id: '9', name: 'Book 6' }, + { id: '10', name: 'Book 6' }, + { id: '11', name: 'Book 6' } + ] + }; + + deleteBookWithId = () => { + const lastOneId = this.state.books.length; + const updatedBooks = this.state.books.filter(m => m.id !== lastOneId.toString()); + this.setState({ books: updatedBooks }); + }; + + addBook = () => { + const lastOneId = this.state.books.length + 1; + this.setState({ books: [...this.state.books, { + id: `${lastOneId}`, name: `Book ${lastOneId}` + }] }); + } + + render() { + const options = { + // pageStartIndex: 0, + sizePerPage: 5, + hideSizePerPage: true, + hidePageListOnlyOnePage: true + }; + const columns = [ + { + dataField: 'id', + text: 'Product ID', + Cell: row => ( +
+ { row.value } +
+ ) + }, + { + dataField: 'name', + text: 'Product Name' + } + ]; + + return ( + + + + + { sourceCode } + + ); + } +} diff --git a/packages/react-bootstrap-table2-example/stories/index.js b/packages/react-bootstrap-table2-example/stories/index.js index 39be4b7..cc97704 100644 --- a/packages/react-bootstrap-table2-example/stories/index.js +++ b/packages/react-bootstrap-table2-example/stories/index.js @@ -163,6 +163,7 @@ import ExpandHooks from 'examples/row-expand/expand-hooks'; // pagination import PaginationTable from 'examples/pagination'; import PaginationHooksTable from 'examples/pagination/pagination-hooks'; +import PaginationWithDynamicData from 'examples/pagination/pagination-with-dynamic-data'; import CustomPaginationTable from 'examples/pagination/custom-pagination'; import CustomPageButtonTable from 'examples/pagination/custom-page-button'; import CustomSizePerPageOptionTable from 'examples/pagination/custom-size-per-page-option'; @@ -404,6 +405,7 @@ storiesOf('Pagination', module) .addDecorator(bootstrapStyle()) .add('Basic Pagination Table', () => ) .add('Pagination Hooks', () => ) + .add('Pagination with Dynamic Data', () => ) .add('Custom Pagination', () => ) .add('Custom Page Button', () => ) .add('Custom Page List', () => ) diff --git a/packages/react-bootstrap-table2-paginator/src/data-context.js b/packages/react-bootstrap-table2-paginator/src/data-context.js index d9e9e01..e33f45f 100644 --- a/packages/react-bootstrap-table2-paginator/src/data-context.js +++ b/packages/react-bootstrap-table2-paginator/src/data-context.js @@ -32,7 +32,12 @@ class PaginationDataProvider extends Provider { // 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); + nextProps.data.length, + this.props.data.length, + this.currPage, + currSizePerPage, + pageStartIndex + ); if (this.currPage !== newPage) { if (onPageChange) { diff --git a/packages/react-bootstrap-table2-paginator/src/page.js b/packages/react-bootstrap-table2-paginator/src/page.js index 1e3e82b..5b63463 100644 --- a/packages/react-bootstrap-table2-paginator/src/page.js +++ b/packages/react-bootstrap-table2-paginator/src/page.js @@ -1,3 +1,5 @@ +import Const from './const'; + const getNormalizedPage = ( page, pageStartIndex @@ -19,12 +21,20 @@ const startIndex = ( export const alignPage = ( dataSize, + prevDataSize, page, sizePerPage, pageStartIndex ) => { - if (page < pageStartIndex || page > (Math.floor(dataSize / sizePerPage) + pageStartIndex)) { - return pageStartIndex; + if (prevDataSize < dataSize) return page; + if (page < pageStartIndex) return pageStartIndex; + if (dataSize <= 0) return pageStartIndex; + if ((page >= (Math.floor(dataSize / sizePerPage) + pageStartIndex)) && pageStartIndex === 1) { + return Math.ceil(dataSize / sizePerPage); + } + if (page >= Math.floor(dataSize / sizePerPage) && pageStartIndex === 0) { + const newPage = Math.ceil(dataSize / sizePerPage); + return newPage - Math.abs((Const.PAGE_START_INDEX - pageStartIndex)); } return page; }; diff --git a/packages/react-bootstrap-table2-paginator/src/state-context.js b/packages/react-bootstrap-table2-paginator/src/state-context.js index 91159f6..83fb4da 100644 --- a/packages/react-bootstrap-table2-paginator/src/state-context.js +++ b/packages/react-bootstrap-table2-paginator/src/state-context.js @@ -117,13 +117,14 @@ class StateProvider extends React.Component { const { pagination: { options } } = this.props; const pageStartIndex = typeof options.pageStartIndex === 'undefined' ? Const.PAGE_START_INDEX : options.pageStartIndex; - this.dataSize = newDataSize; this.currPage = alignPage( newDataSize, + this.dataSize, this.currPage, this.currSizePerPage, pageStartIndex ); + this.dataSize = newDataSize; this.forceUpdate(); } diff --git a/packages/react-bootstrap-table2-paginator/test/page.test.js b/packages/react-bootstrap-table2-paginator/test/page.test.js index aa20c33..e12ae28 100644 --- a/packages/react-bootstrap-table2-paginator/test/page.test.js +++ b/packages/react-bootstrap-table2-paginator/test/page.test.js @@ -43,18 +43,132 @@ describe('Page Functions', () => { }); describe('alignPage', () => { - const pageStartIndex = 1; - const sizePerPage = 10; - const page = 3; - describe('if the page does not fit the pages which calculated from the length of data', () => { - it('should return pageStartIndex argument', () => { - expect(alignPage(15, page, sizePerPage, pageStartIndex)).toEqual(pageStartIndex); + let newDataSize; + let prevDataSize; + let currPage; + let pageStartIndex; + let sizePerPage; + + describe('if prevDataSize < newDataSize', () => { + beforeEach(() => { + newDataSize = 10; + prevDataSize = 6; + currPage = 2; + pageStartIndex = 1; + sizePerPage = 5; + }); + it('should return same page', () => { + expect(alignPage( + newDataSize, + prevDataSize, + currPage, + sizePerPage, + pageStartIndex + )).toEqual(currPage); }); }); - describe('if the length of store.data is large than the end page index', () => { - it('should return current page', () => { - expect(alignPage(30, page, sizePerPage, pageStartIndex)).toEqual(page); + describe('if currPage < newDataSize', () => { + beforeEach(() => { + newDataSize = 10; + prevDataSize = 12; + currPage = 0; + pageStartIndex = 1; + sizePerPage = 5; + }); + + it('should return correct page', () => { + expect(alignPage( + newDataSize, + prevDataSize, + currPage, + sizePerPage, + pageStartIndex + )).toEqual(pageStartIndex); + }); + }); + + describe('if partStartIndex is default 1', () => { + describe('and currPage is bigger than newest last page', () => { + beforeEach(() => { + newDataSize = 9; + prevDataSize = 12; + currPage = 3; + pageStartIndex = 1; + sizePerPage = 5; + }); + + it('should return correct page', () => { + expect(alignPage( + newDataSize, + prevDataSize, + currPage, + sizePerPage, + pageStartIndex + )).toEqual(2); + }); + }); + + describe('and currPage is short than newest last page', () => { + beforeEach(() => { + newDataSize = 11; + prevDataSize = 12; + currPage = 3; + pageStartIndex = 1; + sizePerPage = 5; + }); + + it('should return correct page', () => { + expect(alignPage( + newDataSize, + prevDataSize, + currPage, + sizePerPage, + pageStartIndex + )).toEqual(currPage); + }); + }); + }); + + describe('if partStartIndex is default 0', () => { + describe('and currPage is bigger than newest last page', () => { + beforeEach(() => { + newDataSize = 8; + prevDataSize = 11; + currPage = 2; + pageStartIndex = 0; + sizePerPage = 5; + }); + + it('should return correct page', () => { + expect(alignPage( + newDataSize, + prevDataSize, + currPage, + sizePerPage, + pageStartIndex + )).toEqual(1); + }); + }); + + describe('and currPage is short than newest last page', () => { + beforeEach(() => { + newDataSize = 11; + prevDataSize = 12; + currPage = 2; + pageStartIndex = 0; + sizePerPage = 5; + }); + + it('should return correct page', () => { + expect(alignPage( + newDataSize, + prevDataSize, + currPage, + sizePerPage, + pageStartIndex + )).toEqual(currPage); + }); }); }); });