@@ -105,7 +153,7 @@ export default class Table extends React.Component {
striped
hover
keyField="id"
- data={ products }
+ data={ this.state.products }
columns={ columns }
filter={ filterFactory() }
{ ...paginationTableProps }
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/examples/pagination/standalone-size-per-page.js b/packages/react-bootstrap-table2-example/examples/pagination/standalone-size-per-page.js
index e49b4f1..40526a2 100644
--- a/packages/react-bootstrap-table2-example/examples/pagination/standalone-size-per-page.js
+++ b/packages/react-bootstrap-table2-example/examples/pagination/standalone-size-per-page.js
@@ -84,6 +84,7 @@ export default class StandaloneSizePerPage extends React.Component {
rows.map((row) => {
return row;
});
-export const productsQualityGenerator = (quantity = 5) =>
+export const productsQualityGenerator = (quantity = 5, factor = 0) =>
Array.from({ length: quantity }, (value, index) => ({
- id: index,
- name: `Item name ${index}`,
+ id: index + factor,
+ name: `Item name ${index + factor}`,
quality: index % 3
}));
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-filter/src/context.js b/packages/react-bootstrap-table2-filter/src/context.js
index f54e327..e35711f 100644
--- a/packages/react-bootstrap-table2-filter/src/context.js
+++ b/packages/react-bootstrap-table2-filter/src/context.js
@@ -27,9 +27,8 @@ export default (
this.onFilter = this.onFilter.bind(this);
this.doFilter = this.doFilter.bind(this);
this.onExternalFilter = this.onExternalFilter.bind(this);
- this.state = {
- data: props.data
- };
+ this.data = props.data;
+ this.isEmitDataChange = false;
}
componentDidMount() {
@@ -39,13 +38,10 @@ export default (
}
componentWillReceiveProps(nextProps) {
- let nextData = nextProps.data;
- if (!isRemoteFiltering() && !_.isEqual(nextProps.data, this.state.data)) {
- nextData = this.doFilter(nextProps);
+ // let nextData = nextProps.data;
+ if (!isRemoteFiltering() && !_.isEqual(nextProps.data, this.data)) {
+ this.doFilter(nextProps, undefined, this.isEmitDataChange);
}
- this.setState({
- data: nextData
- });
}
onFilter(column, filterType, initialize = false) {
@@ -83,9 +79,7 @@ export default (
if (filter.props.onFilter) {
result = filter.props.onFilter(filterVal);
}
-
- result = this.doFilter(this.props, result);
- this.setState({ data: result });
+ this.doFilter(this.props, result);
};
}
@@ -95,21 +89,25 @@ export default (
};
}
- doFilter(props, customResult) {
+ doFilter(props, customResult, ignoreEmitDataChange = false) {
let result = customResult;
const { dataChangeListener, data, columns } = props;
result = result || filters(data, columns, _)(this.currFilters);
- if (dataChangeListener) {
+ this.data = result;
+ if (dataChangeListener && !ignoreEmitDataChange) {
+ this.isEmitDataChange = true;
dataChangeListener.emit('filterChanged', result.length);
+ } else {
+ this.isEmitDataChange = false;
+ this.forceUpdate();
}
- return result;
}
render() {
return (
{
expect(onFilter).toHaveBeenCalledWith(filterVal);
});
- it('should set state.data correctly', () => {
+ it('should set data correctly', () => {
instance.onFilter(customColumns[1], FILTER_TYPE.TEXT)(filterVal);
- expect(instance.state.data).toEqual(mockReturn);
+ expect(instance.data).toEqual(mockReturn);
});
});
diff --git a/packages/react-bootstrap-table2-paginator/README.md b/packages/react-bootstrap-table2-paginator/README.md
index ede9040..e5dc52b 100644
--- a/packages/react-bootstrap-table2-paginator/README.md
+++ b/packages/react-bootstrap-table2-paginator/README.md
@@ -190,6 +190,19 @@ import paginationFactory, {
That's it!! The benifit for using standalone is you can much easier to render the standalone component in any posistion. In the future, we will implement more featue like applying `style`, `className` etc on standalone components.
+##### Customizable props for `PaginationListStandalone`
+* N/A
+
+##### Customizable props for `SizePerPageDropdownStandalone`
+* `open`: `true` to make dropdown show.
+* `hidden`: `true` to hide the size per page dropdown.
+* `btnContextual`: Set the button contextual
+* `variation`: Variation for dropdown, available value is `dropdown` and `dropup`.
+* `className`: Custom the class on size per page dropdown
+
+##### Customizable props for `SizePerPageDropdownStandalone`
+* N/A
+
#### 4.2 Customization Everything
If you choose to custom the pagination component by yourself, the `paginationProps` will be important for you. Becasue you have to know for example how to change page or what's the current page etc. Hence, following is all the props in `paginationProps` object:
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/size-per-page-dropdown-adapter.js b/packages/react-bootstrap-table2-paginator/src/size-per-page-dropdown-adapter.js
index adebceb..b2d6a1f 100644
--- a/packages/react-bootstrap-table2-paginator/src/size-per-page-dropdown-adapter.js
+++ b/packages/react-bootstrap-table2-paginator/src/size-per-page-dropdown-adapter.js
@@ -48,6 +48,7 @@ const sizePerPageDropdownAdapter = WrappedComponent =>
}
return (
{
});
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);
+ });
});
});
});
diff --git a/packages/react-bootstrap-table2-toolkit/README.md b/packages/react-bootstrap-table2-toolkit/README.md
index 78fb3a0..c85accc 100644
--- a/packages/react-bootstrap-table2-toolkit/README.md
+++ b/packages/react-bootstrap-table2-toolkit/README.md
@@ -67,6 +67,19 @@ const { SearchBar } = Search;
3. You should render `SearchBar` with `searchProps` as well. The position of `SearchBar` is depends on you.
+### `SearchBar` Props
+#### className - [string]
+Custom the class on input element.
+
+#### placeholder - [string]
+Custom the placeholder on input element.
+
+#### style - [object]
+Custom the style on input element.
+
+#### delay = [number]
+milionsecond for debounce user input.
+
### Search Options
#### defaultSearch - [string]
@@ -127,6 +140,8 @@ const { SearchBar, ClearSearchButton } = Search;
```
+-----
+
## Export CSV
There are two steps to enable the export CSV functionality:
@@ -176,6 +191,8 @@ Default is `true`. `false` will only export current data which display on table.
#### onlyExportSelection - [bool]
Default is `false`. `true` will only export the data which is selected.
+-----
+
## Column Toggle
Let's see how to render the column toggle in your react component:
diff --git a/packages/react-bootstrap-table2/src/body.js b/packages/react-bootstrap-table2/src/body.js
index 2d445fc..a14e1b8 100644
--- a/packages/react-bootstrap-table2/src/body.js
+++ b/packages/react-bootstrap-table2/src/body.js
@@ -17,7 +17,6 @@ class Body extends React.Component {
super(props);
const {
keyField,
- visibleColumnSize,
cellEdit,
selectRow,
expandRow
@@ -34,7 +33,7 @@ class Body extends React.Component {
const expandRowEnabled = !!expandRow.renderer;
if (expandRowEnabled) {
- RowComponent = withRowExpansion(RowAggregator, visibleColumnSize);
+ RowComponent = withRowExpansion(RowAggregator);
}
if (selectRowEnabled) {
diff --git a/packages/react-bootstrap-table2/src/row-expand/row-consumer.js b/packages/react-bootstrap-table2/src/row-expand/row-consumer.js
index 77f5e36..7578d6d 100644
--- a/packages/react-bootstrap-table2/src/row-expand/row-consumer.js
+++ b/packages/react-bootstrap-table2/src/row-expand/row-consumer.js
@@ -3,7 +3,7 @@ import React from 'react';
import ExpandRow from './expand-row';
import ExpansionContext from '../contexts/row-expand-context';
-export default (Component, visibleColumnSize) => {
+export default (Component) => {
const renderWithExpansion = (props, expandRow) => {
const key = props.value;
@@ -20,7 +20,7 @@ export default (Component, visibleColumnSize) => {
/>,
expanded ?
{ expandRow.renderer(props.row) }
: null