diff --git a/packages/react-bootstrap-table2-example/examples/data/load-data-on-the-fly-with-default-filter.js b/packages/react-bootstrap-table2-example/examples/data/load-data-on-the-fly-with-default-filter.js
new file mode 100644
index 000000000..60c8a2288
--- /dev/null
+++ b/packages/react-bootstrap-table2-example/examples/data/load-data-on-the-fly-with-default-filter.js
@@ -0,0 +1,70 @@
+/* eslint react/prop-types: 0 */
+import React from 'react';
+
+import BootstrapTable from 'react-bootstrap-table-next';
+import filterFactory, { textFilter } from 'react-bootstrap-table2-filter';
+import { productsGenerator } from 'utils/common';
+
+const ProductList = (props) => {
+ const columns = [
+ {
+ dataField: 'id',
+ text: 'Product ID'
+ },
+ {
+ dataField: 'name',
+ text: 'Product Name',
+ filter: textFilter({
+ defaultValue: '1'
+ })
+ },
+ {
+ dataField: 'price',
+ text: 'Product Price',
+ filter: textFilter()
+ }
+ ];
+
+ return (
+
+
Products
+
+
+ );
+};
+
+export default class DataContainer extends React.Component {
+ state = {
+ products: productsGenerator(3)
+ };
+
+ loadData = () => {
+ this.setState({
+ products: productsGenerator(14)
+ });
+ }
+
+ render() {
+ return (
+
+ );
+ }
+}
diff --git a/packages/react-bootstrap-table2-example/examples/data/load-data-on-the-fly-with-default-search.js b/packages/react-bootstrap-table2-example/examples/data/load-data-on-the-fly-with-default-search.js
new file mode 100644
index 000000000..d9b08c45b
--- /dev/null
+++ b/packages/react-bootstrap-table2-example/examples/data/load-data-on-the-fly-with-default-search.js
@@ -0,0 +1,80 @@
+/* eslint react/prop-types: 0 */
+import React from 'react';
+
+import BootstrapTable from 'react-bootstrap-table-next';
+import ToolkitProvider, { Search } from 'react-bootstrap-table2-toolkit';
+import { productsGenerator } from 'utils/common';
+
+const { SearchBar } = Search;
+const ProductList = (props) => {
+ const columns = [
+ {
+ dataField: 'id',
+ text: 'Product ID'
+ },
+ {
+ dataField: 'name',
+ text: 'Product Name'
+ },
+ {
+ dataField: 'price',
+ text: 'Product Price'
+ }
+ ];
+
+ return (
+
+
Products
+
+ {
+ toolkitprops => (
+
+
+
+
+ )
+ }
+
+
+ );
+};
+
+export default class DataContainer extends React.Component {
+ state = {
+ products: productsGenerator(3)
+ };
+
+ loadData = () => {
+ this.setState({
+ products: productsGenerator(14)
+ });
+ }
+
+ render() {
+ return (
+
+ );
+ }
+}
diff --git a/packages/react-bootstrap-table2-example/examples/data/load-data-on-the-fly-with-filter.js b/packages/react-bootstrap-table2-example/examples/data/load-data-on-the-fly-with-filter.js
new file mode 100644
index 000000000..c654034d6
--- /dev/null
+++ b/packages/react-bootstrap-table2-example/examples/data/load-data-on-the-fly-with-filter.js
@@ -0,0 +1,68 @@
+/* eslint react/prop-types: 0 */
+import React from 'react';
+
+import BootstrapTable from 'react-bootstrap-table-next';
+import filterFactory, { textFilter } from 'react-bootstrap-table2-filter';
+import { productsGenerator } from 'utils/common';
+
+const ProductList = (props) => {
+ const columns = [
+ {
+ dataField: 'id',
+ text: 'Product ID'
+ },
+ {
+ dataField: 'name',
+ text: 'Product Name',
+ filter: textFilter()
+ },
+ {
+ dataField: 'price',
+ text: 'Product Price',
+ filter: textFilter()
+ }
+ ];
+
+ return (
+
+
Products
+
+
+ );
+};
+
+export default class DataContainer extends React.Component {
+ state = {
+ products: []
+ };
+
+ loadData = () => {
+ this.setState({
+ products: productsGenerator()
+ });
+ }
+
+ render() {
+ return (
+
+ );
+ }
+}
diff --git a/packages/react-bootstrap-table2-example/examples/data/load-data-on-the-fly-with-pagination-and-filter.js b/packages/react-bootstrap-table2-example/examples/data/load-data-on-the-fly-with-pagination-and-filter.js
new file mode 100644
index 000000000..b42a12768
--- /dev/null
+++ b/packages/react-bootstrap-table2-example/examples/data/load-data-on-the-fly-with-pagination-and-filter.js
@@ -0,0 +1,72 @@
+/* eslint react/prop-types: 0 */
+import React from 'react';
+
+import BootstrapTable from 'react-bootstrap-table-next';
+import filterFactory, { textFilter } from 'react-bootstrap-table2-filter';
+import paginationFactory from 'react-bootstrap-table2-paginator';
+import { productsGenerator } from 'utils/common';
+
+const ProductList = (props) => {
+ const columns = [
+ {
+ dataField: 'id',
+ text: 'Product ID'
+ },
+ {
+ dataField: 'name',
+ text: 'Product Name',
+ filter: textFilter({
+ defaultValue: '6'
+ })
+ },
+ {
+ dataField: 'price',
+ text: 'Product Price',
+ filter: textFilter()
+ }
+ ];
+
+ return (
+
+
Products
+
+
+ );
+};
+
+export default class DataContainer extends React.Component {
+ state = {
+ products: productsGenerator(60)
+ };
+
+ loadData = () => {
+ this.setState({
+ products: productsGenerator(14)
+ });
+ }
+
+ render() {
+ return (
+
+ );
+ }
+}
diff --git a/packages/react-bootstrap-table2-example/examples/data/load-data-on-the-fly-with-search.js b/packages/react-bootstrap-table2-example/examples/data/load-data-on-the-fly-with-search.js
new file mode 100644
index 000000000..03540be04
--- /dev/null
+++ b/packages/react-bootstrap-table2-example/examples/data/load-data-on-the-fly-with-search.js
@@ -0,0 +1,80 @@
+/* eslint react/prop-types: 0 */
+import React from 'react';
+
+import BootstrapTable from 'react-bootstrap-table-next';
+import ToolkitProvider, { Search } from 'react-bootstrap-table2-toolkit';
+import { productsGenerator } from 'utils/common';
+
+const { SearchBar } = Search;
+const ProductList = (props) => {
+ const columns = [
+ {
+ dataField: 'id',
+ text: 'Product ID'
+ },
+ {
+ dataField: 'name',
+ text: 'Product Name'
+ },
+ {
+ dataField: 'price',
+ text: 'Product Price'
+ }
+ ];
+
+ return (
+
+
Products
+
+ {
+ toolkitprops => (
+
+
+
+
+ )
+ }
+
+
+ );
+};
+
+export default class DataContainer extends React.Component {
+ state = {
+ products: []
+ };
+
+ loadData = () => {
+ this.setState({
+ products: productsGenerator()
+ });
+ }
+
+ render() {
+ return (
+
+ );
+ }
+}
diff --git a/packages/react-bootstrap-table2-example/stories/index.js b/packages/react-bootstrap-table2-example/stories/index.js
index a7ed50f7f..788b08324 100644
--- a/packages/react-bootstrap-table2-example/stories/index.js
+++ b/packages/react-bootstrap-table2-example/stories/index.js
@@ -205,6 +205,13 @@ import RemoteSearch from 'examples/remote/remote-search';
import RemoteCellEdit from 'examples/remote/remote-celledit';
import RemoteAll from 'examples/remote/remote-all';
+// data
+import LoadDataWithFilter from 'examples/data/load-data-on-the-fly-with-filter';
+import LoadDataWithDefaultFilter from 'examples/data/load-data-on-the-fly-with-default-filter';
+import LoadDataWithSearch from 'examples/data/load-data-on-the-fly-with-search';
+import LoadDataWithDefaultSearch from 'examples/data/load-data-on-the-fly-with-default-search';
+import LoadDataWithPaginationAndFilter from 'examples/data/load-data-on-the-fly-with-pagination-and-filter';
+
// css style
import 'stories/stylesheet/tomorrow.min.css';
import 'stories/stylesheet/storybook.scss';
@@ -433,3 +440,11 @@ storiesOf('Remote', module)
.add('Remote Search', () => )
.add('Remote Cell Editing', () => )
.add('Remote All', () => );
+
+storiesOf('Data', module)
+ .addDecorator(bootstrapStyle())
+ .add('Load data with Filter', () => )
+ .add('Load data with Default Filter', () => )
+ .add('Load data with Search', () => )
+ .add('Load data with Default Search', () => )
+ .add('Load data with Filter and Pagination', () => );
diff --git a/packages/react-bootstrap-table2-filter/src/context.js b/packages/react-bootstrap-table2-filter/src/context.js
index f3edd1fd9..019013faa 100644
--- a/packages/react-bootstrap-table2-filter/src/context.js
+++ b/packages/react-bootstrap-table2-filter/src/context.js
@@ -25,6 +25,7 @@ export default (
super(props);
this.currFilters = {};
this.onFilter = this.onFilter.bind(this);
+ this.doFilter = this.doFilter.bind(this);
this.onExternalFilter = this.onExternalFilter.bind(this);
this.state = {
data: props.data
@@ -38,11 +39,13 @@ export default (
}
componentWillReceiveProps(nextProps) {
- if (isRemoteFiltering()) {
- this.setState({
- data: nextProps.data
- });
+ let nextData = nextProps.data;
+ if (!isRemoteFiltering() && !_.isEqual(nextProps.data, this.props.data)) {
+ nextData = this.doFilter(nextProps);
}
+ this.setState({
+ data: nextData
+ });
}
onFilter(column, filterType, initialize = false) {
@@ -81,11 +84,7 @@ export default (
result = filter.props.onFilter(filterVal);
}
- const { dataChangeListener, data } = this.props;
- result = result || filters(data, this.props.columns, _)(this.currFilters);
- if (dataChangeListener) {
- dataChangeListener.emit('filterChanged', result.length);
- }
+ result = this.doFilter(this.props, result);
this.setState({ data: result });
};
}
@@ -96,6 +95,17 @@ export default (
};
}
+ doFilter(props, customResult) {
+ let result = customResult;
+
+ const { dataChangeListener, data, columns } = props;
+ result = result || filters(data, columns, _)(this.currFilters);
+ if (dataChangeListener) {
+ dataChangeListener.emit('filterChanged', result.length);
+ }
+ return result;
+ }
+
render() {
return (
{
for (let cidx = 0; cidx < columns.length; cidx += 1) {
const column = columns[cidx];
diff --git a/packages/react-bootstrap-table2/src/bootstrap-table.js b/packages/react-bootstrap-table2/src/bootstrap-table.js
index 37ced35bf..0df430c5f 100644
--- a/packages/react-bootstrap-table2/src/bootstrap-table.js
+++ b/packages/react-bootstrap-table2/src/bootstrap-table.js
@@ -106,6 +106,8 @@ class BootstrapTable extends PropsBaseResolver(Component) {
)}
diff --git a/packages/react-bootstrap-table2/src/footer.js b/packages/react-bootstrap-table2/src/footer.js
index 38b2bded6..2c29994ec 100644
--- a/packages/react-bootstrap-table2/src/footer.js
+++ b/packages/react-bootstrap-table2/src/footer.js
@@ -2,31 +2,52 @@
import React from 'react';
import PropTypes from 'prop-types';
+import Const from './const';
import FooterCell from './footer-cell';
import _ from './utils';
const Footer = (props) => {
- const { data, className, columns } = props;
+ const { data, className, columns, selectRow, expandRow } = props;
+ const SelectionFooterCellComp = () => | ;
+ const ExpansionFooterCellComp = () => | ;
+
+ const isRenderExpandColumnInLeft = (
+ expandColumnPosition = Const.INDICATOR_POSITION_LEFT
+ ) => expandColumnPosition === Const.INDICATOR_POSITION_LEFT;
+
+ const childrens = columns.map((column, i) => {
+ if (column.footer === undefined || column.footer === null || column.hidden) {
+ return false;
+ }
+
+ const columnData = _.pluck(data, column.dataField);
+
+ return (
+
+ );
+ });
+
+ if (selectRow && selectRow.hideSelectColumn !== true) {
+ childrens.unshift();
+ }
+
+ if (expandRow.showExpandColumn) {
+ if (isRenderExpandColumnInLeft(expandRow.expandColumnPosition)) {
+ childrens.unshift();
+ } else {
+ childrens.push();
+ }
+ }
return (
- {columns.map((column, i) => {
- if (column.footer === undefined || column.footer === null || column.hidden) {
- return false;
- }
-
- const columnData = _.pluck(data, column.dataField);
-
- return (
-
- );
- })}
+ { childrens }
);
@@ -35,7 +56,9 @@ const Footer = (props) => {
Footer.propTypes = {
data: PropTypes.array,
className: PropTypes.string,
- columns: PropTypes.array
+ columns: PropTypes.array,
+ selectRow: PropTypes.object,
+ expandRow: PropTypes.object
};
export default Footer;
diff --git a/packages/react-bootstrap-table2/test/footer.test.js b/packages/react-bootstrap-table2/test/footer.test.js
index 2a7cc0ac1..3812a49ec 100644
--- a/packages/react-bootstrap-table2/test/footer.test.js
+++ b/packages/react-bootstrap-table2/test/footer.test.js
@@ -1,8 +1,9 @@
/* eslint no-unused-vars: 0 */
import 'jsdom-global/register';
import React from 'react';
-import { shallow, mount } from 'enzyme';
+import { shallow, render } from 'enzyme';
+import Const from '../src/const';
import Footer from '../src/footer';
import FooterCell from '../src/footer-cell';
@@ -32,11 +33,29 @@ describe('Footer', () => {
}
];
+ const selectRow = {
+ mode: Const.ROW_SELECT_DISABLED,
+ selected: [],
+ hideSelectColumn: true
+ };
+ const expandRow = {
+ renderer: undefined,
+ expanded: [],
+ nonExpandable: []
+ };
+
const keyField = 'id';
describe('simplest footer', () => {
beforeEach(() => {
- wrapper = shallow();
+ wrapper = shallow(
+
+ );
});
it('should render successfully', () => {
@@ -50,7 +69,15 @@ describe('Footer', () => {
const className = 'test-class';
beforeEach(() => {
- wrapper = shallow();
+ wrapper = shallow(
+
+ );
});
it('should render successfully', () => {
@@ -58,4 +85,40 @@ describe('Footer', () => {
expect(wrapper.find(`.${className}`).length).toBe(1);
});
});
+
+ describe('when selecrRow prop is enable', () => {
+ beforeEach(() => {
+ wrapper = render(
+
+ );
+ });
+
+ it('should render successfully', () => {
+ expect(wrapper.length).toBe(1);
+ expect(wrapper.find('th').length).toBe(columns.length + 1);
+ });
+ });
+
+ describe('when expandRow prop is enable', () => {
+ beforeEach(() => {
+ wrapper = render(
+
+ );
+ });
+
+ it('should render successfully', () => {
+ expect(wrapper.length).toBe(1);
+ expect(wrapper.find('th').length).toBe(columns.length + 1);
+ });
+ });
});