mirror of
https://github.com/gosticks/react-bootstrap-table2.git
synced 2026-06-29 05:30:05 +00:00
Compare commits
16 Commits
react-boot
...
react-boot
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8e142de332 | ||
|
|
322605f14e | ||
|
|
3156e01dd6 | ||
|
|
052284a163 | ||
|
|
3cd8efffb9 | ||
|
|
447d69cae5 | ||
|
|
cacc28e1bc | ||
|
|
d7f84a9da5 | ||
|
|
63c2630f46 | ||
|
|
903dd2e5c8 | ||
|
|
964faa53e3 | ||
|
|
8fb5364cc2 | ||
|
|
8b89b3de0e | ||
|
|
4506a3dea2 | ||
|
|
ecea3efdaa | ||
|
|
8bef7eb348 |
81
packages/react-bootstrap-table2-example/examples/column-filter/custom-filter-logic.js
vendored
Normal file
81
packages/react-bootstrap-table2-example/examples/column-filter/custom-filter-logic.js
vendored
Normal file
@@ -0,0 +1,81 @@
|
||||
/* eslint eqeqeq: 0 */
|
||||
import React from 'react';
|
||||
import BootstrapTable from 'react-bootstrap-table-next';
|
||||
import filterFactory, { textFilter } from 'react-bootstrap-table2-filter';
|
||||
import Code from 'components/common/code-block';
|
||||
import { productsGenerator } from 'utils/common';
|
||||
|
||||
const products = productsGenerator(8);
|
||||
|
||||
const sourceCode = `\
|
||||
import BootstrapTable from 'react-bootstrap-table-next';
|
||||
import filterFactory, { textFilter } from 'react-bootstrap-table2-filter';
|
||||
|
||||
class Table extends React.Component {
|
||||
filterByPrice = filterVal =>
|
||||
products.filter(product => product.price == filterVal);
|
||||
|
||||
render() {
|
||||
const columns = [{
|
||||
dataField: 'id',
|
||||
text: 'Product ID'
|
||||
}, {
|
||||
dataField: 'name',
|
||||
text: 'Product Name',
|
||||
filter: textFilter()
|
||||
}, {
|
||||
dataField: 'price',
|
||||
text: 'Product Price',
|
||||
filter: textFilter({
|
||||
onFilter: this.filterByPrice
|
||||
})
|
||||
}];
|
||||
|
||||
return (
|
||||
<div>
|
||||
<BootstrapTable
|
||||
keyField="id"
|
||||
data={ products }
|
||||
columns={ columns }
|
||||
filter={ filterFactory() }
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
export default class Table extends React.Component {
|
||||
filterByPrice = filterVal =>
|
||||
products.filter(product => product.price == filterVal);
|
||||
|
||||
render() {
|
||||
const columns = [{
|
||||
dataField: 'id',
|
||||
text: 'Product ID'
|
||||
}, {
|
||||
dataField: 'name',
|
||||
text: 'Product Name',
|
||||
filter: textFilter()
|
||||
}, {
|
||||
dataField: 'price',
|
||||
text: 'Product Price',
|
||||
filter: textFilter({
|
||||
onFilter: this.filterByPrice
|
||||
})
|
||||
}];
|
||||
|
||||
return (
|
||||
<div>
|
||||
<h2>Implement a eq filter on product price column</h2>
|
||||
<BootstrapTable
|
||||
keyField="id"
|
||||
data={ products }
|
||||
columns={ columns }
|
||||
filter={ filterFactory() }
|
||||
/>
|
||||
<Code>{ sourceCode }</Code>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -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 (
|
||||
<div style={ { paddingTop: '20px' } }>
|
||||
<h1 className="h2">Products</h1>
|
||||
<BootstrapTable
|
||||
keyField="id"
|
||||
data={ props.products }
|
||||
columns={ columns }
|
||||
filter={ filterFactory() }
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default class DataContainer extends React.Component {
|
||||
state = {
|
||||
products: productsGenerator(3)
|
||||
};
|
||||
|
||||
loadData = () => {
|
||||
this.setState({
|
||||
products: productsGenerator(14)
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
<button
|
||||
onClick={ this.loadData }
|
||||
style={ {
|
||||
fontSize: '20px',
|
||||
position: 'absolute',
|
||||
left: '200px',
|
||||
top: '40px'
|
||||
} }
|
||||
>
|
||||
Load Data
|
||||
</button>
|
||||
<ProductList products={ this.state.products } />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -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 (
|
||||
<div style={ { paddingTop: '20px' } }>
|
||||
<h1 className="h2">Products</h1>
|
||||
<ToolkitProvider
|
||||
keyField="id"
|
||||
data={ props.products }
|
||||
columns={ columns }
|
||||
search={ { defaultSearch: '2101' } }
|
||||
>
|
||||
{
|
||||
toolkitprops => (
|
||||
<div>
|
||||
<SearchBar { ...toolkitprops.searchProps } />
|
||||
<BootstrapTable
|
||||
striped
|
||||
hover
|
||||
{ ...toolkitprops.baseProps }
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
</ToolkitProvider>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default class DataContainer extends React.Component {
|
||||
state = {
|
||||
products: productsGenerator(3)
|
||||
};
|
||||
|
||||
loadData = () => {
|
||||
this.setState({
|
||||
products: productsGenerator(14)
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
<button
|
||||
onClick={ this.loadData }
|
||||
style={ {
|
||||
fontSize: '20px',
|
||||
position: 'absolute',
|
||||
left: '200px',
|
||||
top: '40px'
|
||||
} }
|
||||
>
|
||||
Load Data
|
||||
</button>
|
||||
<ProductList products={ this.state.products } />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
68
packages/react-bootstrap-table2-example/examples/data/load-data-on-the-fly-with-filter.js
vendored
Normal file
68
packages/react-bootstrap-table2-example/examples/data/load-data-on-the-fly-with-filter.js
vendored
Normal file
@@ -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 (
|
||||
<div style={ { paddingTop: '20px' } }>
|
||||
<h1 className="h2">Products</h1>
|
||||
<BootstrapTable
|
||||
keyField="id"
|
||||
data={ props.products }
|
||||
columns={ columns }
|
||||
filter={ filterFactory() }
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default class DataContainer extends React.Component {
|
||||
state = {
|
||||
products: []
|
||||
};
|
||||
|
||||
loadData = () => {
|
||||
this.setState({
|
||||
products: productsGenerator()
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
<button
|
||||
onClick={ this.loadData }
|
||||
style={ {
|
||||
fontSize: '20px',
|
||||
position: 'absolute',
|
||||
left: '200px',
|
||||
top: '40px'
|
||||
} }
|
||||
>
|
||||
Load Data
|
||||
</button>
|
||||
<ProductList products={ this.state.products } />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -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 (
|
||||
<div style={ { paddingTop: '20px' } }>
|
||||
<h1 className="h2">Products</h1>
|
||||
<BootstrapTable
|
||||
keyField="id"
|
||||
data={ props.products }
|
||||
columns={ columns }
|
||||
filter={ filterFactory() }
|
||||
pagination={ paginationFactory() }
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default class DataContainer extends React.Component {
|
||||
state = {
|
||||
products: productsGenerator(60)
|
||||
};
|
||||
|
||||
loadData = () => {
|
||||
this.setState({
|
||||
products: productsGenerator(14)
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
<button
|
||||
onClick={ this.loadData }
|
||||
style={ {
|
||||
fontSize: '20px',
|
||||
position: 'absolute',
|
||||
left: '200px',
|
||||
top: '40px'
|
||||
} }
|
||||
>
|
||||
Load Data
|
||||
</button>
|
||||
<ProductList products={ this.state.products } />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
80
packages/react-bootstrap-table2-example/examples/data/load-data-on-the-fly-with-search.js
vendored
Normal file
80
packages/react-bootstrap-table2-example/examples/data/load-data-on-the-fly-with-search.js
vendored
Normal file
@@ -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 (
|
||||
<div style={ { paddingTop: '20px' } }>
|
||||
<h1 className="h2">Products</h1>
|
||||
<ToolkitProvider
|
||||
keyField="id"
|
||||
data={ props.products }
|
||||
columns={ columns }
|
||||
search
|
||||
>
|
||||
{
|
||||
toolkitprops => (
|
||||
<div>
|
||||
<SearchBar { ...toolkitprops.searchProps } />
|
||||
<BootstrapTable
|
||||
striped
|
||||
hover
|
||||
{ ...toolkitprops.baseProps }
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
</ToolkitProvider>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default class DataContainer extends React.Component {
|
||||
state = {
|
||||
products: []
|
||||
};
|
||||
|
||||
loadData = () => {
|
||||
this.setState({
|
||||
products: productsGenerator()
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
<button
|
||||
onClick={ this.loadData }
|
||||
style={ {
|
||||
fontSize: '20px',
|
||||
position: 'absolute',
|
||||
left: '200px',
|
||||
top: '40px'
|
||||
} }
|
||||
>
|
||||
Load Data
|
||||
</button>
|
||||
<ProductList products={ this.state.products } />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
139
packages/react-bootstrap-table2-example/examples/pagination/custom-page-list-with-search.js
vendored
Normal file
139
packages/react-bootstrap-table2-example/examples/pagination/custom-page-list-with-search.js
vendored
Normal file
@@ -0,0 +1,139 @@
|
||||
/* eslint react/prefer-stateless-function: 0 */
|
||||
import React from 'react';
|
||||
|
||||
import BootstrapTable from 'react-bootstrap-table-next';
|
||||
import paginationFactory, { PaginationProvider, PaginationListStandalone } from 'react-bootstrap-table2-paginator';
|
||||
import ToolkitProvider, { Search } from 'react-bootstrap-table2-toolkit';
|
||||
import Code from 'components/common/code-block';
|
||||
import { productsGenerator } from 'utils/common';
|
||||
|
||||
const products = productsGenerator(21);
|
||||
const { SearchBar } = Search;
|
||||
|
||||
const columns = [{
|
||||
dataField: 'id',
|
||||
text: 'Product ID'
|
||||
}, {
|
||||
dataField: 'name',
|
||||
text: 'Product Name'
|
||||
}];
|
||||
|
||||
const sourceCode = `\
|
||||
import BootstrapTable from 'react-bootstrap-table-next';
|
||||
import paginationFactory, { PaginationProvider, PaginationListStandalone } from 'react-bootstrap-table2-paginator';
|
||||
import filterFactory, { textFilter } from 'react-bootstrap-table2-filter';
|
||||
|
||||
class Table extends React.Component {
|
||||
render() {
|
||||
const options = {
|
||||
custom: true,
|
||||
paginationSize: 4,
|
||||
pageStartIndex: 1,
|
||||
firstPageText: 'First',
|
||||
prePageText: 'Back',
|
||||
nextPageText: 'Next',
|
||||
lastPageText: 'Last',
|
||||
nextPageTitle: 'First page',
|
||||
prePageTitle: 'Pre page',
|
||||
firstPageTitle: 'Next page',
|
||||
lastPageTitle: 'Last page',
|
||||
showTotal: true,
|
||||
totalSize: products.length
|
||||
};
|
||||
const contentTable = ({ paginationProps, paginationTableProps }) => (
|
||||
<div>
|
||||
<PaginationListStandalone { ...paginationProps } />
|
||||
<div>
|
||||
<div>
|
||||
<BootstrapTable
|
||||
striped
|
||||
hover
|
||||
keyField="id"
|
||||
data={ products }
|
||||
columns={ columns }
|
||||
filter={ filterFactory() }
|
||||
cellEdit={ cellEditFactory() }
|
||||
{ ...paginationTableProps }
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<PaginationListStandalone { ...paginationProps } />
|
||||
</div>
|
||||
);
|
||||
|
||||
return (
|
||||
<div>
|
||||
<h2>PaginationProvider will care the data size change. You dont do anything</h2>
|
||||
<PaginationProvider
|
||||
pagination={
|
||||
paginationFactory(options)
|
||||
}
|
||||
>
|
||||
{ contentTable }
|
||||
</PaginationProvider>
|
||||
<Code>{ sourceCode }</Code>
|
||||
</div >
|
||||
);
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
export default class Table extends React.Component {
|
||||
render() {
|
||||
const options = {
|
||||
custom: true,
|
||||
paginationSize: 4,
|
||||
pageStartIndex: 1,
|
||||
firstPageText: 'First',
|
||||
prePageText: 'Back',
|
||||
nextPageText: 'Next',
|
||||
lastPageText: 'Last',
|
||||
nextPageTitle: 'First page',
|
||||
prePageTitle: 'Pre page',
|
||||
firstPageTitle: 'Next page',
|
||||
lastPageTitle: 'Last page',
|
||||
showTotal: true,
|
||||
totalSize: products.length
|
||||
};
|
||||
const contentTable = ({ paginationProps, paginationTableProps }) => (
|
||||
<div>
|
||||
<PaginationListStandalone { ...paginationProps } />
|
||||
<ToolkitProvider
|
||||
keyField="id"
|
||||
columns={ columns }
|
||||
data={ products }
|
||||
search
|
||||
>
|
||||
{
|
||||
toolkitprops => (
|
||||
<div>
|
||||
<SearchBar { ...toolkitprops.searchProps } />
|
||||
<BootstrapTable
|
||||
striped
|
||||
hover
|
||||
{ ...toolkitprops.baseProps }
|
||||
{ ...paginationTableProps }
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
</ToolkitProvider>
|
||||
<PaginationListStandalone { ...paginationProps } />
|
||||
</div>
|
||||
);
|
||||
|
||||
return (
|
||||
<div>
|
||||
<h2>PaginationProvider will care the data size change. You dont do anything</h2>
|
||||
<PaginationProvider
|
||||
pagination={
|
||||
paginationFactory(options)
|
||||
}
|
||||
>
|
||||
{ contentTable }
|
||||
</PaginationProvider>
|
||||
<Code>{ sourceCode }</Code>
|
||||
</div >
|
||||
);
|
||||
}
|
||||
}
|
||||
133
packages/react-bootstrap-table2-example/examples/pagination/custome-page-list-with-filter.js
vendored
Normal file
133
packages/react-bootstrap-table2-example/examples/pagination/custome-page-list-with-filter.js
vendored
Normal file
@@ -0,0 +1,133 @@
|
||||
/* eslint react/prefer-stateless-function: 0 */
|
||||
import React from 'react';
|
||||
|
||||
import BootstrapTable from 'react-bootstrap-table-next';
|
||||
import paginationFactory, { PaginationProvider, PaginationListStandalone } from 'react-bootstrap-table2-paginator';
|
||||
import filterFactory, { textFilter } from 'react-bootstrap-table2-filter';
|
||||
import Code from 'components/common/code-block';
|
||||
import { productsGenerator } from 'utils/common';
|
||||
|
||||
const products = productsGenerator(21);
|
||||
|
||||
const columns = [{
|
||||
dataField: 'id',
|
||||
text: 'Product ID',
|
||||
filter: textFilter({})
|
||||
}, {
|
||||
dataField: 'name',
|
||||
text: 'Product Name',
|
||||
filter: textFilter()
|
||||
}];
|
||||
|
||||
const sourceCode = `\
|
||||
import BootstrapTable from 'react-bootstrap-table-next';
|
||||
import paginationFactory, { PaginationProvider, PaginationListStandalone } from 'react-bootstrap-table2-paginator';
|
||||
import filterFactory, { textFilter } from 'react-bootstrap-table2-filter';
|
||||
|
||||
class Table extends React.Component {
|
||||
render() {
|
||||
const options = {
|
||||
custom: true,
|
||||
paginationSize: 4,
|
||||
pageStartIndex: 1,
|
||||
firstPageText: 'First',
|
||||
prePageText: 'Back',
|
||||
nextPageText: 'Next',
|
||||
lastPageText: 'Last',
|
||||
nextPageTitle: 'First page',
|
||||
prePageTitle: 'Pre page',
|
||||
firstPageTitle: 'Next page',
|
||||
lastPageTitle: 'Last page',
|
||||
showTotal: true,
|
||||
totalSize: products.length
|
||||
};
|
||||
const contentTable = ({ paginationProps, paginationTableProps }) => (
|
||||
<div>
|
||||
<PaginationListStandalone { ...paginationProps } />
|
||||
<div>
|
||||
<div>
|
||||
<BootstrapTable
|
||||
striped
|
||||
hover
|
||||
keyField="id"
|
||||
data={ products }
|
||||
columns={ columns }
|
||||
filter={ filterFactory() }
|
||||
cellEdit={ cellEditFactory() }
|
||||
{ ...paginationTableProps }
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<PaginationListStandalone { ...paginationProps } />
|
||||
</div>
|
||||
);
|
||||
|
||||
return (
|
||||
<div>
|
||||
<h2>PaginationProvider will care the data size change. You dont do anything</h2>
|
||||
<PaginationProvider
|
||||
pagination={
|
||||
paginationFactory(options)
|
||||
}
|
||||
>
|
||||
{ contentTable }
|
||||
</PaginationProvider>
|
||||
<Code>{ sourceCode }</Code>
|
||||
</div >
|
||||
);
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
export default class Table extends React.Component {
|
||||
render() {
|
||||
const options = {
|
||||
custom: true,
|
||||
paginationSize: 4,
|
||||
pageStartIndex: 1,
|
||||
firstPageText: 'First',
|
||||
prePageText: 'Back',
|
||||
nextPageText: 'Next',
|
||||
lastPageText: 'Last',
|
||||
nextPageTitle: 'First page',
|
||||
prePageTitle: 'Pre page',
|
||||
firstPageTitle: 'Next page',
|
||||
lastPageTitle: 'Last page',
|
||||
showTotal: true,
|
||||
totalSize: products.length
|
||||
};
|
||||
const contentTable = ({ paginationProps, paginationTableProps }) => (
|
||||
<div>
|
||||
<PaginationListStandalone { ...paginationProps } />
|
||||
<div>
|
||||
<div>
|
||||
<BootstrapTable
|
||||
striped
|
||||
hover
|
||||
keyField="id"
|
||||
data={ products }
|
||||
columns={ columns }
|
||||
filter={ filterFactory() }
|
||||
{ ...paginationTableProps }
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<PaginationListStandalone { ...paginationProps } />
|
||||
</div>
|
||||
);
|
||||
|
||||
return (
|
||||
<div>
|
||||
<h2>PaginationProvider will care the data size change. You dont do anything</h2>
|
||||
<PaginationProvider
|
||||
pagination={
|
||||
paginationFactory(options)
|
||||
}
|
||||
>
|
||||
{ contentTable }
|
||||
</PaginationProvider>
|
||||
<Code>{ sourceCode }</Code>
|
||||
</div >
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "react-bootstrap-table2-example",
|
||||
"version": "1.0.15",
|
||||
"version": "1.0.17",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"private": true,
|
||||
|
||||
@@ -87,6 +87,7 @@ import CustomFilter from 'examples/column-filter/custom-filter';
|
||||
import AdvanceCustomFilter from 'examples/column-filter/advance-custom-filter';
|
||||
import ClearAllFilters from 'examples/column-filter/clear-all-filters';
|
||||
import FilterHooks from 'examples/column-filter/filter-hooks';
|
||||
import CustomFilterLogic from 'examples/column-filter/custom-filter-logic';
|
||||
|
||||
// work on rows
|
||||
import RowStyleTable from 'examples/rows/row-style';
|
||||
@@ -169,6 +170,8 @@ import StandalonePaginationList from 'examples/pagination/standalone-pagination-
|
||||
import StandaloneSizePerPage from 'examples/pagination/standalone-size-per-page';
|
||||
import FullyCustomPaginationTable from 'examples/pagination/fully-custom-pagination';
|
||||
import RemoteStandalonePaginationTable from 'examples/pagination/remote-standalone-pagination';
|
||||
import CustomePaginationWithFilter from 'examples/pagination/custome-page-list-with-filter';
|
||||
import CustomePaginationWithSearch from 'examples/pagination/custom-page-list-with-search';
|
||||
|
||||
// search
|
||||
import SearchTable from 'examples/search';
|
||||
@@ -202,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';
|
||||
@@ -289,7 +299,8 @@ storiesOf('Column Filter', module)
|
||||
.add('Advance Custom Filter', () => <AdvanceCustomFilter />)
|
||||
.add('Preserved Option Order on Select Filter', () => <SelectFilterWithPreservedOptionsOrder />)
|
||||
.add('Clear All Filters', () => <ClearAllFilters />)
|
||||
.add('Filter Hooks', () => <FilterHooks />);
|
||||
.add('Filter Hooks', () => <FilterHooks />)
|
||||
.add('Implement custom filter logic', () => <CustomFilterLogic />);
|
||||
|
||||
storiesOf('Work on Rows', module)
|
||||
.addDecorator(bootstrapStyle())
|
||||
@@ -390,7 +401,9 @@ storiesOf('Pagination', module)
|
||||
.add('Standalone Pagination List', () => <StandalonePaginationList />)
|
||||
.add('Standalone SizePerPage Dropdown', () => <StandaloneSizePerPage />)
|
||||
.add('Fully Custom Pagination', () => <FullyCustomPaginationTable />)
|
||||
.add('Remote Fully Custom Pagination', () => <RemoteStandalonePaginationTable />);
|
||||
.add('Remote Fully Custom Pagination', () => <RemoteStandalonePaginationTable />)
|
||||
.add('Custom Pagination with Filter', () => <CustomePaginationWithFilter />)
|
||||
.add('Custom Pagination with Search', () => <CustomePaginationWithSearch />);
|
||||
|
||||
storiesOf('Table Search', module)
|
||||
.addDecorator(bootstrapStyle())
|
||||
@@ -427,3 +440,11 @@ storiesOf('Remote', module)
|
||||
.add('Remote Search', () => <RemoteSearch />)
|
||||
.add('Remote Cell Editing', () => <RemoteCellEdit />)
|
||||
.add('Remote All', () => <RemoteAll />);
|
||||
|
||||
storiesOf('Data', module)
|
||||
.addDecorator(bootstrapStyle())
|
||||
.add('Load data with Filter', () => <LoadDataWithFilter />)
|
||||
.add('Load data with Default Filter', () => <LoadDataWithDefaultFilter />)
|
||||
.add('Load data with Search', () => <LoadDataWithSearch />)
|
||||
.add('Load data with Default Search', () => <LoadDataWithDefaultSearch />)
|
||||
.add('Load data with Filter and Pagination', () => <LoadDataWithPaginationAndFilter />);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "react-bootstrap-table2-filter",
|
||||
"version": "1.1.2",
|
||||
"version": "1.1.4",
|
||||
"description": "it's a column filter addon for react-bootstrap-table2",
|
||||
"main": "./lib/index.js",
|
||||
"repository": {
|
||||
|
||||
@@ -17,14 +17,19 @@ export default (
|
||||
class FilterProvider extends React.Component {
|
||||
static propTypes = {
|
||||
data: PropTypes.array.isRequired,
|
||||
columns: PropTypes.array.isRequired
|
||||
columns: PropTypes.array.isRequired,
|
||||
dataChangeListener: PropTypes.object
|
||||
}
|
||||
|
||||
constructor(props) {
|
||||
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
|
||||
};
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
@@ -33,6 +38,16 @@ export default (
|
||||
}
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
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) {
|
||||
return (filterVal) => {
|
||||
// watch out here if migration to context API, #334
|
||||
@@ -64,11 +79,13 @@ export default (
|
||||
return;
|
||||
}
|
||||
|
||||
let result;
|
||||
if (filter.props.onFilter) {
|
||||
filter.props.onFilter(filterVal);
|
||||
result = filter.props.onFilter(filterVal);
|
||||
}
|
||||
|
||||
this.forceUpdate();
|
||||
result = this.doFilter(this.props, result);
|
||||
this.setState({ data: result });
|
||||
};
|
||||
}
|
||||
|
||||
@@ -78,14 +95,21 @@ export default (
|
||||
};
|
||||
}
|
||||
|
||||
render() {
|
||||
let { data } = this.props;
|
||||
if (!isRemoteFiltering()) {
|
||||
data = filters(data, this.props.columns, _)(this.currFilters);
|
||||
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 (
|
||||
<FilterContext.Provider value={ {
|
||||
data,
|
||||
data: this.state.data,
|
||||
onFilter: this.onFilter,
|
||||
onExternalFilter: this.onExternalFilter
|
||||
} }
|
||||
|
||||
@@ -45,7 +45,8 @@ describe('FilterContext', () => {
|
||||
|
||||
function shallowContext(
|
||||
enableRemote = false,
|
||||
tableColumns = columns
|
||||
tableColumns = columns,
|
||||
dataChangeListener,
|
||||
) {
|
||||
mockBase.mockReset();
|
||||
handleFilterChange.mockReset();
|
||||
@@ -59,6 +60,7 @@ describe('FilterContext', () => {
|
||||
<FilterContext.Provider
|
||||
columns={ tableColumns }
|
||||
data={ data }
|
||||
dataChangeListener={ dataChangeListener }
|
||||
>
|
||||
<FilterContext.Consumer>
|
||||
{
|
||||
@@ -252,6 +254,58 @@ describe('FilterContext', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('if filter.props.onFilter is defined and return an undefined data', () => {
|
||||
const mockReturn = [{
|
||||
id: 1,
|
||||
name: 'A'
|
||||
}];
|
||||
const filterVal = 'A';
|
||||
const onFilter = jest.fn().mockReturnValue(mockReturn);
|
||||
const customColumns = columns.map((column, i) => {
|
||||
if (i === 1) {
|
||||
return {
|
||||
...column,
|
||||
filter: textFilter({ onFilter })
|
||||
};
|
||||
}
|
||||
return column;
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
wrapper = shallow(shallowContext(false, customColumns));
|
||||
wrapper.render();
|
||||
instance = wrapper.instance();
|
||||
});
|
||||
|
||||
it('should call filter.props.onFilter correctly', () => {
|
||||
instance.onFilter(customColumns[1], FILTER_TYPE.TEXT)(filterVal);
|
||||
expect(onFilter).toHaveBeenCalledTimes(1);
|
||||
expect(onFilter).toHaveBeenCalledWith(filterVal);
|
||||
});
|
||||
|
||||
it('should set state.data correctly', () => {
|
||||
instance.onFilter(customColumns[1], FILTER_TYPE.TEXT)(filterVal);
|
||||
expect(instance.state.data).toEqual(mockReturn);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when props.dataChangeListener is defined', () => {
|
||||
const filterVal = '3';
|
||||
const newDataLength = 0;
|
||||
const dataChangeListener = { emit: jest.fn() };
|
||||
|
||||
beforeEach(() => {
|
||||
wrapper = shallow(shallowContext(false, columns, dataChangeListener));
|
||||
wrapper.render();
|
||||
instance = wrapper.instance();
|
||||
});
|
||||
|
||||
it('should call dataChangeListener.emit correctly', () => {
|
||||
instance.onFilter(columns[1], FILTER_TYPE.TEXT)(filterVal);
|
||||
expect(dataChangeListener.emit).toHaveBeenCalledWith('filterChanged', newDataLength);
|
||||
});
|
||||
});
|
||||
|
||||
describe('combination', () => {
|
||||
beforeEach(() => {
|
||||
wrapper = shallow(shallowContext());
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "react-bootstrap-table2-paginator",
|
||||
"version": "2.0.1",
|
||||
"version": "2.0.2",
|
||||
"description": "it's the pagination addon for react-bootstrap-table2",
|
||||
"main": "./lib/index.js",
|
||||
"repository": {
|
||||
|
||||
@@ -2,7 +2,9 @@
|
||||
/* eslint react/require-default-props: 0 */
|
||||
/* eslint no-lonely-if: 0 */
|
||||
import React from 'react';
|
||||
import EventEmitter from 'events';
|
||||
import Const from './const';
|
||||
import { alignPage } from './page';
|
||||
|
||||
const StateContext = React.createContext();
|
||||
|
||||
@@ -10,6 +12,7 @@ class StateProvider extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.handleChangePage = this.handleChangePage.bind(this);
|
||||
this.handleDataSizeChange = this.handleDataSizeChange.bind(this);
|
||||
this.handleChangeSizePerPage = this.handleChangeSizePerPage.bind(this);
|
||||
|
||||
let currPage;
|
||||
@@ -36,7 +39,10 @@ class StateProvider extends React.Component {
|
||||
}
|
||||
|
||||
this.currPage = currPage;
|
||||
this.dataSize = options.totalSize;
|
||||
this.currSizePerPage = currSizePerPage;
|
||||
this.dataChangeListener = new EventEmitter();
|
||||
this.dataChangeListener.on('filterChanged', this.handleDataSizeChange);
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
@@ -46,12 +52,13 @@ class StateProvider extends React.Component {
|
||||
if (this.isRemotePagination() || custom) {
|
||||
this.currPage = nextProps.pagination.options.page;
|
||||
this.currSizePerPage = nextProps.pagination.options.sizePerPage;
|
||||
this.dataSize = nextProps.pagination.options.totalSize;
|
||||
}
|
||||
}
|
||||
|
||||
getPaginationProps = () => {
|
||||
const { pagination: { options }, bootstrap4 } = this.props;
|
||||
const { currPage, currSizePerPage } = this;
|
||||
const { currPage, currSizePerPage, dataSize } = this;
|
||||
const withFirstAndLast = typeof options.withFirstAndLast === 'undefined' ?
|
||||
Const.With_FIRST_AND_LAST : options.withFirstAndLast;
|
||||
const alwaysShowAllBtns = typeof options.alwaysShowAllBtns === 'undefined' ?
|
||||
@@ -72,7 +79,7 @@ class StateProvider extends React.Component {
|
||||
hideSizePerPage,
|
||||
alwaysShowAllBtns,
|
||||
withFirstAndLast,
|
||||
dataSize: options.totalSize,
|
||||
dataSize,
|
||||
sizePerPageList: options.sizePerPageList || Const.SIZE_PER_PAGE_LIST,
|
||||
paginationSize: options.paginationSize || Const.PAGINATION_SIZE,
|
||||
showTotal: options.showTotal,
|
||||
@@ -106,6 +113,20 @@ class StateProvider extends React.Component {
|
||||
return e.result;
|
||||
};
|
||||
|
||||
handleDataSizeChange(newDataSize) {
|
||||
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.currPage,
|
||||
this.currSizePerPage,
|
||||
pageStartIndex
|
||||
);
|
||||
this.forceUpdate();
|
||||
}
|
||||
|
||||
handleChangePage(currPage) {
|
||||
const { currSizePerPage } = this;
|
||||
const { pagination: { options } } = this.props;
|
||||
@@ -153,7 +174,8 @@ class StateProvider extends React.Component {
|
||||
paginationProps,
|
||||
paginationTableProps: {
|
||||
pagination,
|
||||
setPaginationRemoteEmitter: this.setPaginationRemoteEmitter
|
||||
setPaginationRemoteEmitter: this.setPaginationRemoteEmitter,
|
||||
dataChangeListener: this.dataChangeListener
|
||||
}
|
||||
} }
|
||||
>
|
||||
|
||||
@@ -91,6 +91,10 @@ describe('PaginationStateContext', () => {
|
||||
expect(wrapper.instance().currSizePerPage).toEqual(Const.SIZE_PER_PAGE_LIST[0]);
|
||||
});
|
||||
|
||||
it('should have correct dataSize', () => {
|
||||
expect(wrapper.instance().dataSize).toEqual(options.totalSize);
|
||||
});
|
||||
|
||||
it('should get correct pagination props', () => {
|
||||
const instance = wrapper.instance();
|
||||
expect(wrapper.length).toBe(1);
|
||||
@@ -102,7 +106,8 @@ describe('PaginationStateContext', () => {
|
||||
createContext: expect.any(Function),
|
||||
options: instance.getPaginationProps()
|
||||
},
|
||||
setPaginationRemoteEmitter: instance.setPaginationRemoteEmitter
|
||||
setPaginationRemoteEmitter: instance.setPaginationRemoteEmitter,
|
||||
dataChangeListener: expect.any(Object)
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -149,7 +154,7 @@ describe('PaginationStateContext', () => {
|
||||
setRemotePaginationEmitter(instance, true);
|
||||
nextProps = {
|
||||
data,
|
||||
pagination: { ...defaultPagination, options: { page: 3, sizePerPage: 5 } }
|
||||
pagination: { ...defaultPagination, options: { page: 3, sizePerPage: 5, totalSize: 50 } }
|
||||
};
|
||||
instance.componentWillReceiveProps(nextProps);
|
||||
});
|
||||
@@ -157,6 +162,7 @@ describe('PaginationStateContext', () => {
|
||||
it('should always reset currPage and currSizePerPage', () => {
|
||||
expect(instance.currPage).toEqual(nextProps.pagination.options.page);
|
||||
expect(instance.currSizePerPage).toEqual(nextProps.pagination.options.sizePerPage);
|
||||
expect(instance.dataSize).toEqual(nextProps.pagination.options.totalSize);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -170,7 +176,10 @@ describe('PaginationStateContext', () => {
|
||||
setRemotePaginationEmitter(instance, true);
|
||||
nextProps = {
|
||||
data,
|
||||
pagination: { ...defaultPagination, options: { page: 3, sizePerPage: 5, custom: true } }
|
||||
pagination: {
|
||||
...defaultPagination,
|
||||
options: { page: 3, sizePerPage: 5, custom: true, totalSize: 50 }
|
||||
}
|
||||
};
|
||||
instance.componentWillReceiveProps(nextProps);
|
||||
});
|
||||
@@ -178,10 +187,36 @@ describe('PaginationStateContext', () => {
|
||||
it('should always reset currPage and currSizePerPage', () => {
|
||||
expect(instance.currPage).toEqual(nextProps.pagination.options.page);
|
||||
expect(instance.currSizePerPage).toEqual(nextProps.pagination.options.sizePerPage);
|
||||
expect(instance.dataSize).toEqual(nextProps.pagination.options.totalSize);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('handleDataSizeChange', () => {
|
||||
let instance;
|
||||
const newTotalSize = 8;
|
||||
beforeEach(() => {
|
||||
wrapper = shallow(shallowContext({
|
||||
...defaultPagination,
|
||||
page: 3
|
||||
}));
|
||||
instance = wrapper.instance();
|
||||
setRemotePaginationEmitter(instance);
|
||||
jest.spyOn(instance, 'forceUpdate');
|
||||
instance.handleDataSizeChange(newTotalSize);
|
||||
});
|
||||
|
||||
it('should update dataSize correctly', () => {
|
||||
expect(instance.dataSize).toEqual(newTotalSize);
|
||||
expect(instance.forceUpdate).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it('should update currPage correctly if page list shrink', () => {
|
||||
expect(instance.currPage).toEqual(Const.PAGE_START_INDEX);
|
||||
expect(instance.forceUpdate).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
});
|
||||
|
||||
describe('handleChangePage', () => {
|
||||
let instance;
|
||||
const newPage = 3;
|
||||
@@ -343,7 +378,8 @@ describe('PaginationStateContext', () => {
|
||||
createContext: expect.any(Function),
|
||||
options: instance.getPaginationProps()
|
||||
},
|
||||
setPaginationRemoteEmitter: instance.setPaginationRemoteEmitter
|
||||
setPaginationRemoteEmitter: instance.setPaginationRemoteEmitter,
|
||||
dataChangeListener: expect.any(Object)
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -374,7 +410,8 @@ describe('PaginationStateContext', () => {
|
||||
createContext: expect.any(Function),
|
||||
options: instance.getPaginationProps()
|
||||
},
|
||||
setPaginationRemoteEmitter: instance.setPaginationRemoteEmitter
|
||||
setPaginationRemoteEmitter: instance.setPaginationRemoteEmitter,
|
||||
dataChangeListener: expect.any(Object)
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -401,7 +438,8 @@ describe('PaginationStateContext', () => {
|
||||
createContext: expect.any(Function),
|
||||
options: instance.getPaginationProps()
|
||||
},
|
||||
setPaginationRemoteEmitter: instance.setPaginationRemoteEmitter
|
||||
setPaginationRemoteEmitter: instance.setPaginationRemoteEmitter,
|
||||
dataChangeListener: expect.any(Object)
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -428,7 +466,8 @@ describe('PaginationStateContext', () => {
|
||||
createContext: expect.any(Function),
|
||||
options: instance.getPaginationProps()
|
||||
},
|
||||
setPaginationRemoteEmitter: instance.setPaginationRemoteEmitter
|
||||
setPaginationRemoteEmitter: instance.setPaginationRemoteEmitter,
|
||||
dataChangeListener: expect.any(Object)
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -455,7 +494,8 @@ describe('PaginationStateContext', () => {
|
||||
createContext: expect.any(Function),
|
||||
options: instance.getPaginationProps()
|
||||
},
|
||||
setPaginationRemoteEmitter: instance.setPaginationRemoteEmitter
|
||||
setPaginationRemoteEmitter: instance.setPaginationRemoteEmitter,
|
||||
dataChangeListener: expect.any(Object)
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -482,7 +522,8 @@ describe('PaginationStateContext', () => {
|
||||
createContext: expect.any(Function),
|
||||
options: instance.getPaginationProps()
|
||||
},
|
||||
setPaginationRemoteEmitter: instance.setPaginationRemoteEmitter
|
||||
setPaginationRemoteEmitter: instance.setPaginationRemoteEmitter,
|
||||
dataChangeListener: expect.any(Object)
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -509,7 +550,8 @@ describe('PaginationStateContext', () => {
|
||||
createContext: expect.any(Function),
|
||||
options: instance.getPaginationProps()
|
||||
},
|
||||
setPaginationRemoteEmitter: instance.setPaginationRemoteEmitter
|
||||
setPaginationRemoteEmitter: instance.setPaginationRemoteEmitter,
|
||||
dataChangeListener: expect.any(Object)
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -536,7 +578,8 @@ describe('PaginationStateContext', () => {
|
||||
createContext: expect.any(Function),
|
||||
options: instance.getPaginationProps()
|
||||
},
|
||||
setPaginationRemoteEmitter: instance.setPaginationRemoteEmitter
|
||||
setPaginationRemoteEmitter: instance.setPaginationRemoteEmitter,
|
||||
dataChangeListener: expect.any(Object)
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -563,7 +606,8 @@ describe('PaginationStateContext', () => {
|
||||
createContext: expect.any(Function),
|
||||
options: instance.getPaginationProps()
|
||||
},
|
||||
setPaginationRemoteEmitter: instance.setPaginationRemoteEmitter
|
||||
setPaginationRemoteEmitter: instance.setPaginationRemoteEmitter,
|
||||
dataChangeListener: expect.any(Object)
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -590,7 +634,8 @@ describe('PaginationStateContext', () => {
|
||||
createContext: expect.any(Function),
|
||||
options: instance.getPaginationProps()
|
||||
},
|
||||
setPaginationRemoteEmitter: instance.setPaginationRemoteEmitter
|
||||
setPaginationRemoteEmitter: instance.setPaginationRemoteEmitter,
|
||||
dataChangeListener: expect.any(Object)
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -617,7 +662,8 @@ describe('PaginationStateContext', () => {
|
||||
createContext: expect.any(Function),
|
||||
options: instance.getPaginationProps()
|
||||
},
|
||||
setPaginationRemoteEmitter: instance.setPaginationRemoteEmitter
|
||||
setPaginationRemoteEmitter: instance.setPaginationRemoteEmitter,
|
||||
dataChangeListener: expect.any(Object)
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -644,7 +690,8 @@ describe('PaginationStateContext', () => {
|
||||
createContext: expect.any(Function),
|
||||
options: instance.getPaginationProps()
|
||||
},
|
||||
setPaginationRemoteEmitter: instance.setPaginationRemoteEmitter
|
||||
setPaginationRemoteEmitter: instance.setPaginationRemoteEmitter,
|
||||
dataChangeListener: expect.any(Object)
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -671,7 +718,8 @@ describe('PaginationStateContext', () => {
|
||||
createContext: expect.any(Function),
|
||||
options: instance.getPaginationProps()
|
||||
},
|
||||
setPaginationRemoteEmitter: instance.setPaginationRemoteEmitter
|
||||
setPaginationRemoteEmitter: instance.setPaginationRemoteEmitter,
|
||||
dataChangeListener: expect.any(Object)
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -698,7 +746,8 @@ describe('PaginationStateContext', () => {
|
||||
createContext: expect.any(Function),
|
||||
options: instance.getPaginationProps()
|
||||
},
|
||||
setPaginationRemoteEmitter: instance.setPaginationRemoteEmitter
|
||||
setPaginationRemoteEmitter: instance.setPaginationRemoteEmitter,
|
||||
dataChangeListener: expect.any(Object)
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -725,7 +774,8 @@ describe('PaginationStateContext', () => {
|
||||
createContext: expect.any(Function),
|
||||
options: instance.getPaginationProps()
|
||||
},
|
||||
setPaginationRemoteEmitter: instance.setPaginationRemoteEmitter
|
||||
setPaginationRemoteEmitter: instance.setPaginationRemoteEmitter,
|
||||
dataChangeListener: expect.any(Object)
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -752,7 +802,8 @@ describe('PaginationStateContext', () => {
|
||||
createContext: expect.any(Function),
|
||||
options: instance.getPaginationProps()
|
||||
},
|
||||
setPaginationRemoteEmitter: instance.setPaginationRemoteEmitter
|
||||
setPaginationRemoteEmitter: instance.setPaginationRemoteEmitter,
|
||||
dataChangeListener: expect.any(Object)
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -779,7 +830,8 @@ describe('PaginationStateContext', () => {
|
||||
createContext: expect.any(Function),
|
||||
options: instance.getPaginationProps()
|
||||
},
|
||||
setPaginationRemoteEmitter: instance.setPaginationRemoteEmitter
|
||||
setPaginationRemoteEmitter: instance.setPaginationRemoteEmitter,
|
||||
dataChangeListener: expect.any(Object)
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -806,7 +858,8 @@ describe('PaginationStateContext', () => {
|
||||
createContext: expect.any(Function),
|
||||
options: instance.getPaginationProps()
|
||||
},
|
||||
setPaginationRemoteEmitter: instance.setPaginationRemoteEmitter
|
||||
setPaginationRemoteEmitter: instance.setPaginationRemoteEmitter,
|
||||
dataChangeListener: expect.any(Object)
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -833,7 +886,8 @@ describe('PaginationStateContext', () => {
|
||||
createContext: expect.any(Function),
|
||||
options: instance.getPaginationProps()
|
||||
},
|
||||
setPaginationRemoteEmitter: instance.setPaginationRemoteEmitter
|
||||
setPaginationRemoteEmitter: instance.setPaginationRemoteEmitter,
|
||||
dataChangeListener: expect.any(Object)
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "react-bootstrap-table2-toolkit",
|
||||
"version": "1.2.0",
|
||||
"version": "1.2.2",
|
||||
"description": "The toolkit for react-bootstrap-table2",
|
||||
"main": "./lib/index.js",
|
||||
"repository": {
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
/* eslint react/prop-types: 0 */
|
||||
/* eslint react/require-default-props: 0 */
|
||||
/* eslint no-continue: 0 */
|
||||
/* eslint no-lonely-if: 0 */
|
||||
/* eslint class-methods-use-this: 0 */
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
@@ -17,36 +19,55 @@ export default (options = {
|
||||
static propTypes = {
|
||||
data: PropTypes.array.isRequired,
|
||||
columns: PropTypes.array.isRequired,
|
||||
searchText: PropTypes.string
|
||||
searchText: PropTypes.string,
|
||||
dataChangeListener: PropTypes.object
|
||||
}
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.performRemoteSearch = props.searchText !== '';
|
||||
let initialData = props.data;
|
||||
if (isRemoteSearch() && this.props.searchText !== '') {
|
||||
handleRemoteSearchChange(this.props.searchText);
|
||||
} else {
|
||||
initialData = this.search(props);
|
||||
this.triggerListener(initialData);
|
||||
}
|
||||
this.state = { data: initialData };
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
if (isRemoteSearch()) {
|
||||
if (nextProps.searchText !== this.props.searchText) {
|
||||
this.performRemoteSearch = true;
|
||||
} else {
|
||||
this.performRemoteSearch = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
search() {
|
||||
const { data, columns } = this.props;
|
||||
let { searchText } = this.props;
|
||||
|
||||
if (isRemoteSearch()) {
|
||||
if (this.performRemoteSearch) {
|
||||
handleRemoteSearchChange(searchText);
|
||||
handleRemoteSearchChange(nextProps.searchText);
|
||||
} else {
|
||||
const result = this.search(nextProps);
|
||||
this.triggerListener(result);
|
||||
this.setState({
|
||||
data: result
|
||||
});
|
||||
}
|
||||
} else {
|
||||
if (isRemoteSearch()) {
|
||||
this.setState({ data: nextProps.data });
|
||||
} else if (!_.isEqual(nextProps.data, this.props.data)) {
|
||||
const result = this.search(nextProps);
|
||||
this.triggerListener(result);
|
||||
this.setState({
|
||||
data: result
|
||||
});
|
||||
}
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
searchText = searchText.toLowerCase();
|
||||
triggerListener(result) {
|
||||
if (this.props.dataChangeListener) {
|
||||
this.props.dataChangeListener.emit('filterChanged', result.length);
|
||||
}
|
||||
}
|
||||
|
||||
search(props) {
|
||||
const { data, columns } = props;
|
||||
const searchText = props.searchText.toLowerCase();
|
||||
return data.filter((row, ridx) => {
|
||||
for (let cidx = 0; cidx < columns.length; cidx += 1) {
|
||||
const column = columns[cidx];
|
||||
@@ -69,9 +90,8 @@ export default (options = {
|
||||
}
|
||||
|
||||
render() {
|
||||
const data = this.search();
|
||||
return (
|
||||
<SearchContext.Provider value={ { data } }>
|
||||
<SearchContext.Provider value={ { data: this.state.data } }>
|
||||
{ this.props.children }
|
||||
</SearchContext.Provider>
|
||||
);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "react-bootstrap-table-next",
|
||||
"version": "2.1.0",
|
||||
"version": "2.1.2",
|
||||
"description": "Next generation of react-bootstrap-table",
|
||||
"main": "./lib/index.js",
|
||||
"repository": {
|
||||
|
||||
42
packages/react-bootstrap-table2/src/body.js
vendored
42
packages/react-bootstrap-table2/src/body.js
vendored
@@ -15,9 +15,36 @@ import withRowExpansion from './row-expand/row-consumer';
|
||||
class Body extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
if (props.cellEdit.createContext) {
|
||||
this.EditingCell = props.cellEdit.createEditingCell(_, props.cellEdit.options.onStartEdit);
|
||||
const {
|
||||
keyField,
|
||||
visibleColumnSize,
|
||||
cellEdit,
|
||||
selectRow,
|
||||
expandRow
|
||||
} = props;
|
||||
|
||||
// Construct Editing Cell Component
|
||||
if (cellEdit.createContext) {
|
||||
this.EditingCell = cellEdit.createEditingCell(_, cellEdit.options.onStartEdit);
|
||||
}
|
||||
|
||||
// Construct Row Component
|
||||
let RowComponent = SimpleRow;
|
||||
const selectRowEnabled = selectRow.mode !== Const.ROW_SELECT_DISABLED;
|
||||
const expandRowEnabled = !!expandRow.renderer;
|
||||
|
||||
if (expandRowEnabled) {
|
||||
RowComponent = withRowExpansion(RowAggregator, visibleColumnSize);
|
||||
}
|
||||
|
||||
if (selectRowEnabled) {
|
||||
RowComponent = withRowSelection(expandRowEnabled ? RowComponent : RowAggregator);
|
||||
}
|
||||
|
||||
if (cellEdit.createContext) {
|
||||
RowComponent = cellEdit.withRowLevelCellEdit(RowComponent, selectRowEnabled, keyField, _);
|
||||
}
|
||||
this.RowComponent = RowComponent;
|
||||
}
|
||||
|
||||
render() {
|
||||
@@ -46,21 +73,12 @@ class Body extends React.Component {
|
||||
}
|
||||
content = <RowSection content={ indication } colSpan={ visibleColumnSize } />;
|
||||
} else {
|
||||
let RowComponent = SimpleRow;
|
||||
const selectRowEnabled = selectRow.mode !== Const.ROW_SELECT_DISABLED;
|
||||
const expandRowEnabled = !!expandRow.renderer;
|
||||
|
||||
const additionalRowProps = {};
|
||||
if (expandRowEnabled) {
|
||||
RowComponent = withRowExpansion(RowAggregator, visibleColumnSize);
|
||||
}
|
||||
|
||||
if (selectRowEnabled) {
|
||||
RowComponent = withRowSelection(expandRowEnabled ? RowComponent : RowAggregator);
|
||||
}
|
||||
|
||||
if (cellEdit.createContext) {
|
||||
RowComponent = cellEdit.withRowLevelCellEdit(RowComponent, selectRowEnabled, keyField, _);
|
||||
additionalRowProps.EditingCellComponent = this.EditingCell;
|
||||
}
|
||||
|
||||
@@ -88,7 +106,7 @@ class Body extends React.Component {
|
||||
baseRowProps.style = _.isFunction(rowStyle) ? rowStyle(row, index) : rowStyle;
|
||||
baseRowProps.className = (_.isFunction(rowClasses) ? rowClasses(row, index) : rowClasses);
|
||||
|
||||
return <RowComponent { ...baseRowProps } />;
|
||||
return <this.RowComponent { ...baseRowProps } />;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -106,6 +106,8 @@ class BootstrapTable extends PropsBaseResolver(Component) {
|
||||
<Footer
|
||||
data={ this.getData() }
|
||||
columns={ columns }
|
||||
selectRow={ selectRow }
|
||||
expandRow={ expandRow }
|
||||
className={ this.props.footerClasses }
|
||||
/>
|
||||
)}
|
||||
|
||||
@@ -217,6 +217,7 @@ const withContext = Base =>
|
||||
ref={ n => this.searchContext = n }
|
||||
data={ rootProps.getData(filterProps) }
|
||||
searchText={ this.props.search.searchText }
|
||||
dataChangeListener={ this.props.dataChangeListener }
|
||||
>
|
||||
<this.SearchContext.Consumer>
|
||||
{
|
||||
@@ -237,6 +238,7 @@ const withContext = Base =>
|
||||
{ ...baseProps }
|
||||
ref={ n => this.filterContext = n }
|
||||
data={ rootProps.getData() }
|
||||
dataChangeListener={ this.props.dataChangeListener }
|
||||
>
|
||||
<this.FilterContext.Consumer>
|
||||
{
|
||||
|
||||
37
packages/react-bootstrap-table2/src/footer.js
vendored
37
packages/react-bootstrap-table2/src/footer.js
vendored
@@ -2,16 +2,20 @@
|
||||
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 = () => <th />;
|
||||
const ExpansionFooterCellComp = () => <th />;
|
||||
|
||||
return (
|
||||
<tfoot>
|
||||
<tr className={ className }>
|
||||
{columns.map((column, i) => {
|
||||
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;
|
||||
}
|
||||
@@ -26,7 +30,24 @@ const Footer = (props) => {
|
||||
columnData={ columnData }
|
||||
/>
|
||||
);
|
||||
})}
|
||||
});
|
||||
|
||||
if (selectRow && selectRow.hideSelectColumn !== true) {
|
||||
childrens.unshift(<SelectionFooterCellComp key="selection" />);
|
||||
}
|
||||
|
||||
if (expandRow.showExpandColumn) {
|
||||
if (isRenderExpandColumnInLeft(expandRow.expandColumnPosition)) {
|
||||
childrens.unshift(<ExpansionFooterCellComp key="expansion" />);
|
||||
} else {
|
||||
childrens.push(<ExpansionFooterCellComp key="expansion" />);
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<tfoot>
|
||||
<tr className={ className }>
|
||||
{ childrens }
|
||||
</tr>
|
||||
</tfoot>
|
||||
);
|
||||
@@ -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;
|
||||
|
||||
@@ -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(<Footer data={ data } columns={ columns } />);
|
||||
wrapper = shallow(
|
||||
<Footer
|
||||
data={ data }
|
||||
columns={ columns }
|
||||
selectRow={ selectRow }
|
||||
expandRow={ expandRow }
|
||||
/>
|
||||
);
|
||||
});
|
||||
|
||||
it('should render successfully', () => {
|
||||
@@ -50,7 +69,15 @@ describe('Footer', () => {
|
||||
const className = 'test-class';
|
||||
|
||||
beforeEach(() => {
|
||||
wrapper = shallow(<Footer data={ data } columns={ columns } className={ className } />);
|
||||
wrapper = shallow(
|
||||
<Footer
|
||||
data={ data }
|
||||
columns={ columns }
|
||||
className={ className }
|
||||
selectRow={ selectRow }
|
||||
expandRow={ expandRow }
|
||||
/>
|
||||
);
|
||||
});
|
||||
|
||||
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(
|
||||
<Footer
|
||||
data={ data }
|
||||
columns={ columns }
|
||||
selectRow={ { ...selectRow, mode: 'radio', hideSelectColumn: false } }
|
||||
expandRow={ expandRow }
|
||||
/>
|
||||
);
|
||||
});
|
||||
|
||||
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(
|
||||
<Footer
|
||||
data={ data }
|
||||
columns={ columns }
|
||||
selectRow={ selectRow }
|
||||
expandRow={ { expandRow, showExpandColumn: true } }
|
||||
/>
|
||||
);
|
||||
});
|
||||
|
||||
it('should render successfully', () => {
|
||||
expect(wrapper.length).toBe(1);
|
||||
expect(wrapper.find('th').length).toBe(columns.length + 1);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user