This commit is contained in:
AllenFang 2019-03-09 18:18:20 +08:00
parent a3b3ce0dc4
commit 921e8c7ecc
5 changed files with 88 additions and 36 deletions

View File

@ -3,28 +3,70 @@ import React from 'react';
import BootstrapTable from 'react-bootstrap-table-next'; import BootstrapTable from 'react-bootstrap-table-next';
import paginationFactory, { PaginationProvider, PaginationListStandalone } from 'react-bootstrap-table2-paginator'; import paginationFactory, { PaginationProvider, PaginationListStandalone } from 'react-bootstrap-table2-paginator';
import filterFactory, { textFilter } from 'react-bootstrap-table2-filter'; import filterFactory, { textFilter, selectFilter } from 'react-bootstrap-table2-filter';
import Code from 'components/common/code-block'; import Code from 'components/common/code-block';
import { productsGenerator } from 'utils/common'; import { productsQualityGenerator } from 'utils/common';
const products = productsGenerator(21); const products = productsQualityGenerator(21);
const selectOptions = {
0: 'good',
1: 'Bad',
2: 'unknown'
};
const columns = [{ const columns = [{
dataField: 'id', dataField: 'id',
text: 'Product ID', text: 'Product ID'
filter: textFilter({})
}, { }, {
dataField: 'name', dataField: 'name',
text: 'Product Name', text: 'Product Name',
filter: textFilter() filter: textFilter()
}, {
dataField: 'quality',
text: 'Product Quailty',
formatter: cell => selectOptions[cell],
filter: selectFilter({
options: selectOptions,
defaultValue: 0
})
}]; }];
const sourceCode = `\ const sourceCode = `\
import BootstrapTable from 'react-bootstrap-table-next'; import BootstrapTable from 'react-bootstrap-table-next';
import paginationFactory, { PaginationProvider, PaginationListStandalone } from 'react-bootstrap-table2-paginator'; import paginationFactory, { PaginationProvider, PaginationListStandalone } from 'react-bootstrap-table2-paginator';
import filterFactory, { textFilter } from 'react-bootstrap-table2-filter'; import filterFactory, { textFilter, selectFilter } from 'react-bootstrap-table2-filter';
const selectOptions = {
0: 'good',
1: 'Bad',
2: 'unknown'
};
const columns = [{
dataField: 'id',
text: 'Product ID'
}, {
dataField: 'name',
text: 'Product Name',
filter: textFilter()
}, {
dataField: 'quality',
text: 'Product Quailty',
formatter: cell => selectOptions[cell],
filter: selectFilter({
options: selectOptions,
defaultValue: 0
})
}];
class Table extends React.Component { class Table extends React.Component {
state = { products }
loadData = () => {
this.setState({ products: productsQualityGenerator(40, 7) });
}
render() { render() {
const options = { const options = {
custom: true, custom: true,
@ -39,10 +81,11 @@ class Table extends React.Component {
firstPageTitle: 'Next page', firstPageTitle: 'Next page',
lastPageTitle: 'Last page', lastPageTitle: 'Last page',
showTotal: true, showTotal: true,
totalSize: products.length totalSize: this.state.products.length
}; };
const contentTable = ({ paginationProps, paginationTableProps }) => ( const contentTable = ({ paginationProps, paginationTableProps }) => (
<div> <div>
<button className="btn btn-default" onClick={ this.loadData }>Load Another Data</button>
<PaginationListStandalone { ...paginationProps } /> <PaginationListStandalone { ...paginationProps } />
<div> <div>
<div> <div>
@ -50,10 +93,9 @@ class Table extends React.Component {
striped striped
hover hover
keyField="id" keyField="id"
data={ products } data={ this.state.products }
columns={ columns } columns={ columns }
filter={ filterFactory() } filter={ filterFactory() }
cellEdit={ cellEditFactory() }
{ ...paginationTableProps } { ...paginationTableProps }
/> />
</div> </div>
@ -72,7 +114,6 @@ class Table extends React.Component {
> >
{ contentTable } { contentTable }
</PaginationProvider> </PaginationProvider>
<Code>{ sourceCode }</Code>
</div > </div >
); );
} }
@ -80,6 +121,12 @@ class Table extends React.Component {
`; `;
export default class Table extends React.Component { export default class Table extends React.Component {
state = { products }
loadData = () => {
this.setState({ products: productsQualityGenerator(40, 7) });
}
render() { render() {
const options = { const options = {
custom: true, custom: true,
@ -94,10 +141,11 @@ export default class Table extends React.Component {
firstPageTitle: 'Next page', firstPageTitle: 'Next page',
lastPageTitle: 'Last page', lastPageTitle: 'Last page',
showTotal: true, showTotal: true,
totalSize: products.length totalSize: this.state.products.length
}; };
const contentTable = ({ paginationProps, paginationTableProps }) => ( const contentTable = ({ paginationProps, paginationTableProps }) => (
<div> <div>
<button className="btn btn-default" onClick={ this.loadData }>Load Another Data</button>
<PaginationListStandalone { ...paginationProps } /> <PaginationListStandalone { ...paginationProps } />
<div> <div>
<div> <div>
@ -105,7 +153,7 @@ export default class Table extends React.Component {
striped striped
hover hover
keyField="id" keyField="id"
data={ products } data={ this.state.products }
columns={ columns } columns={ columns }
filter={ filterFactory() } filter={ filterFactory() }
{ ...paginationTableProps } { ...paginationTableProps }

View File

@ -29,10 +29,10 @@ export const withOnSale = rows => rows.map((row) => {
return row; return row;
}); });
export const productsQualityGenerator = (quantity = 5) => export const productsQualityGenerator = (quantity = 5, factor = 0) =>
Array.from({ length: quantity }, (value, index) => ({ Array.from({ length: quantity }, (value, index) => ({
id: index, id: index + factor,
name: `Item name ${index}`, name: `Item name ${index + factor}`,
quality: index % 3 quality: index % 3
})); }));

View File

@ -27,9 +27,8 @@ export default (
this.onFilter = this.onFilter.bind(this); this.onFilter = this.onFilter.bind(this);
this.doFilter = this.doFilter.bind(this); this.doFilter = this.doFilter.bind(this);
this.onExternalFilter = this.onExternalFilter.bind(this); this.onExternalFilter = this.onExternalFilter.bind(this);
this.state = { this.data = props.data;
data: props.data this.isEmitDataChange = false;
};
} }
componentDidMount() { componentDidMount() {
@ -39,13 +38,10 @@ export default (
} }
componentWillReceiveProps(nextProps) { componentWillReceiveProps(nextProps) {
let nextData = nextProps.data; // let nextData = nextProps.data;
if (!isRemoteFiltering() && !_.isEqual(nextProps.data, this.state.data)) { if (!isRemoteFiltering() && !_.isEqual(nextProps.data, this.data)) {
nextData = this.doFilter(nextProps); this.doFilter(nextProps, undefined, this.isEmitDataChange);
} }
this.setState({
data: nextData
});
} }
onFilter(column, filterType, initialize = false) { onFilter(column, filterType, initialize = false) {
@ -83,9 +79,7 @@ export default (
if (filter.props.onFilter) { if (filter.props.onFilter) {
result = filter.props.onFilter(filterVal); result = filter.props.onFilter(filterVal);
} }
this.doFilter(this.props, result);
result = this.doFilter(this.props, result);
this.setState({ data: result });
}; };
} }
@ -95,21 +89,25 @@ export default (
}; };
} }
doFilter(props, customResult) { doFilter(props, customResult, ignoreEmitDataChange = false) {
let result = customResult; let result = customResult;
const { dataChangeListener, data, columns } = props; const { dataChangeListener, data, columns } = props;
result = result || filters(data, columns, _)(this.currFilters); result = result || filters(data, columns, _)(this.currFilters);
if (dataChangeListener) { this.data = result;
if (dataChangeListener && !ignoreEmitDataChange) {
this.isEmitDataChange = true;
dataChangeListener.emit('filterChanged', result.length); dataChangeListener.emit('filterChanged', result.length);
} else {
this.isEmitDataChange = false;
this.forceUpdate();
} }
return result;
} }
render() { render() {
return ( return (
<FilterContext.Provider value={ { <FilterContext.Provider value={ {
data: this.state.data, data: this.data,
onFilter: this.onFilter, onFilter: this.onFilter,
onExternalFilter: this.onExternalFilter onExternalFilter: this.onExternalFilter
} } } }

View File

@ -283,9 +283,9 @@ describe('FilterContext', () => {
expect(onFilter).toHaveBeenCalledWith(filterVal); expect(onFilter).toHaveBeenCalledWith(filterVal);
}); });
it('should set state.data correctly', () => { it('should set data correctly', () => {
instance.onFilter(customColumns[1], FILTER_TYPE.TEXT)(filterVal); instance.onFilter(customColumns[1], FILTER_TYPE.TEXT)(filterVal);
expect(instance.state.data).toEqual(mockReturn); expect(instance.data).toEqual(mockReturn);
}); });
}); });

View File

@ -50,9 +50,15 @@ class StateProvider extends React.Component {
// user should align the page when the page is not fit to the data size when remote enable // user should align the page when the page is not fit to the data size when remote enable
if (this.isRemotePagination() || custom) { if (this.isRemotePagination() || custom) {
this.currPage = nextProps.pagination.options.page; if (typeof nextProps.pagination.options.page !== 'undefined') {
this.currSizePerPage = nextProps.pagination.options.sizePerPage; this.currPage = nextProps.pagination.options.page;
this.dataSize = nextProps.pagination.options.totalSize; }
if (typeof nextProps.pagination.options.sizePerPage !== 'undefined') {
this.currSizePerPage = nextProps.pagination.options.sizePerPage;
}
if (typeof nextProps.pagination.options.totalSize !== 'undefined') {
this.dataSize = nextProps.pagination.options.totalSize;
}
} }
} }