Compare commits

..

22 Commits

Author SHA1 Message Date
AllenFang
497bf44192 Publish
- react-bootstrap-table2-editor@1.2.3
 - react-bootstrap-table2-example@1.0.23
 - react-bootstrap-table2-filter@1.1.8
 - react-bootstrap-table-next@3.1.0
2019-04-02 21:33:49 +08:00
Allen
fcefcf8c84 Merge pull request #886 from react-bootstrap-table/develop
20190331 release
2019-04-02 21:25:03 +08:00
Allen
04e3af0bbb Merge pull request #861 from react-bootstrap-table/feature/row-expand-animate
Feature/row expand animate
2019-03-31 16:02:13 +08:00
AllenFang
9f47fa009c lock version 2019-03-31 15:33:43 +08:00
Alek Lefebvre
0edf9c8891 fix #808 (#874) 2019-03-31 15:17:57 +08:00
AllenFang
df5024892c Publish
- react-bootstrap-table2-example@1.0.22
 - react-bootstrap-table2-paginator@2.0.5
 - react-bootstrap-table-next@3.0.3
2019-03-26 20:41:04 +08:00
Allen
4448c3f28c Merge pull request #875 from react-bootstrap-table/develop
20190326 release
2019-03-26 20:39:13 +08:00
AllenFang
196ae33295 fix #859 2019-03-25 23:07:22 +08:00
AllenFang
7f1b7a6c97 fix #838 2019-03-24 20:52:26 +08:00
AllenFang
a6ccafcc75 fix #866 2019-03-24 16:55:56 +08:00
AllenFang
06d87299a3 Publish
- react-bootstrap-table2-example@1.0.21
 - react-bootstrap-table2-filter@1.1.7
 - react-bootstrap-table2-toolkit@1.4.0
 - react-bootstrap-table-next@3.0.2
2019-03-18 00:31:24 +08:00
Allen
5891ec1b93 Merge pull request #862 from react-bootstrap-table/develop
20190317 release
2019-03-18 00:28:47 +08:00
AllenFang
c5d9e04c2c fix #817 2019-03-17 16:30:39 +08:00
AllenFang
dba3da28c1 Merge branch 'YassienW-animate-row-expansion' into feature/row-expand-animate 2019-03-17 15:24:07 +08:00
AllenFang
a0e09cd804 fix conflicts 2019-03-17 15:20:16 +08:00
AllenFang
d0e70f7246 fix #852 2019-03-17 14:43:39 +08:00
henning-kvinnesland
b93c683f17 Fix typo. (#855)
`to cusom the sort caret` => `to customize the sort-caret`
2019-03-17 13:30:35 +08:00
henning-kvinnesland
f80e1ea66c Fix typo. (#856)
`chagne` => `change`
2019-03-17 13:30:21 +08:00
AllenFang
7642bfa1a3 fix #849 2019-03-17 13:29:17 +08:00
Yassien
8f304a849f Animation now works with custom expand management 2019-03-16 19:03:22 +02:00
Yassien
33c026c7e2 Added original padding without breaking the animation 2019-02-25 13:01:42 +02:00
Yassien
d84fd5c801 CSS Animation for row expansion 2019-02-23 22:40:05 +02:00
28 changed files with 432 additions and 187 deletions

View File

@@ -164,7 +164,7 @@ Enable the column sort via a `true` value given.
``` ```
## <a name='sortCaret'>column.sortCaret - [Function]</a> ## <a name='sortCaret'>column.sortCaret - [Function]</a>
Use`column.sortCaret` to custom the sort caret. This callback function accept two arguments: `order` and `column` Use`column.sortCaret` to customize the sort caret. This callback function accept two arguments: `order` and `column`
```js ```js
{ {

View File

@@ -2,7 +2,7 @@
# Row expand # Row expand
`react-bootstrap-table2` supports the row expand feature. By passing prop `expandRow` to enable this functionality. `react-bootstrap-table2` supports the row expand feature. By passing prop `expandRow` to enable this functionality.
> Default is click to expand/collapse a row. In addition, we don't support any way to chagne this mechanism! > Default is click to expand/collapse a row. In addition, we don't support any way to change this mechanism!
## Required ## Required
* [renderer (**required**)](#renderer) * [renderer (**required**)](#renderer)

View File

@@ -132,7 +132,7 @@ const columns = [
if (typeof cell !== 'object') { if (typeof cell !== 'object') {
dateObj = new Date(cell); dateObj = new Date(cell);
} }
return `${('0' + dateObj.getDate()).slice(-2)}/${('0' + (dateObj.getMonth() + 1)).slice(-2)}/${dateObj.getFullYear()}`; return `${('0' + dateObj.getUTCDate()).slice(-2)}/${('0' + (dateObj.getUTCMonth() + 1)).slice(-2)}/${dateObj.getUTCFullYear()}`;
}, },
editor: { editor: {
type: Type.DATE type: Type.DATE

View File

@@ -1,6 +1,6 @@
{ {
"name": "react-bootstrap-table2-editor", "name": "react-bootstrap-table2-editor",
"version": "1.2.2", "version": "1.2.3",
"description": "it's the editor addon for react-bootstrap-table2", "description": "it's the editor addon for react-bootstrap-table2",
"main": "./lib/index.js", "main": "./lib/index.js",
"scripts": { "scripts": {

View File

@@ -23,7 +23,7 @@ const columns = [{
if (typeof cell !== 'object') { if (typeof cell !== 'object') {
dateObj = new Date(cell); dateObj = new Date(cell);
} }
return `${('0' + dateObj.getDate()).slice(-2)}/${('0' + (dateObj.getMonth() + 1)).slice(-2)}/${dateObj.getFullYear()}`; return `${('0' + dateObj.getUTCDate()).slice(-2)}/${('0' + (dateObj.getUTCMonth() + 1)).slice(-2)}/${dateObj.getUTCFullYear()}`;
}, },
editor: { editor: {
type: Type.DATE type: Type.DATE
@@ -48,7 +48,7 @@ const columns = [{
if (typeof cell !== 'object') { if (typeof cell !== 'object') {
dateObj = new Date(cell); dateObj = new Date(cell);
} }
return \`$\{('0' + dateObj.getDate()).slice(-2)}/$\{('0' + (dateObj.getMonth() + 1)).slice(-2)}/$\{dateObj.getFullYear()}\`; return \`$\{('0' + dateObj.getUTCDate()).slice(-2)}/$\{('0' + (dateObj.getUTCMonth() + 1)).slice(-2)}/$\{dateObj.getUTCFullYear()}\`;
}, },
editor: { editor: {
type: Type.DATE type: Type.DATE

View File

@@ -11,141 +11,13 @@ const products = [
{ id: 14, name: 'Item 14', price: 14.5, inStock: true } { id: 14, name: 'Item 14', price: 14.5, inStock: true }
]; ];
const columns = [
{
dataField: 'id',
text: 'Product ID'
},
{
dataField: 'name',
text: 'Product Name'
},
{
dataField: 'price',
text: 'Product Price'
},
{
dataField: 'inStock',
text: 'In Stock',
formatter: (cellContent, row) => (
<div className="checkbox disabled">
<label>
<input type="checkbox" checked={ row.inStock } disabled />
</label>
</div>
)
},
{
dataField: 'df1',
isDummyField: true,
text: 'Action 1',
formatter: (cellContent, row) => {
if (row.inStock) {
return (
<h5>
<span className="label label-success"> Available</span>
</h5>
);
}
return (
<h5>
<span className="label label-danger"> Backordered</span>
</h5>
);
}
},
{
dataField: 'df2',
isDummyField: true,
text: 'Action 2',
formatter: (cellContent, row) => {
if (row.inStock) {
return (
<h5>
<span className="label label-success"> Available</span>
</h5>
);
}
return (
<h5>
<span className="label label-danger"> Backordered</span>
</h5>
);
}
}
];
const sourceCode = `\ const sourceCode = `\
import BootstrapTable from 'react-bootstrap-table-next'; import BootstrapTable from 'react-bootstrap-table-next';
const columns = [
{
dataField: 'id',
text: 'Product ID'
},
{
dataField: 'name',
text: 'Product Name'
},
{
dataField: 'price',
text: 'Product Price'
},
{
dataField: 'inStock',
text: 'In Stock',
formatter: (cellContent, row) => (
<div className="checkbox disabled">
<label>
<input type="checkbox" checked={ row.inStock } disabled />
</label>
</div>
)
},
{
dataField: 'df1',
isDummyField: true,
text: 'Action 1',
formatter: (cellContent, row) => {
if (row.inStock) {
return (
<h5>
<span className="label label-success"> Available</span>
</h5>
);
}
return (
<h5>
<span className="label label-danger"> Backordered</span>
</h5>
);
}
},
{
dataField: 'df2',
isDummyField: true,
text: 'Action 2',
formatter: (cellContent, row) => {
if (row.inStock) {
return (
<h5>
<span className="label label-success"> Available</span>
</h5>
);
}
return (
<h5>
<span className="label label-danger"> Backordered</span>
</h5>
);
}
}
];
class ProductList extends React.Component { class ProductList extends React.Component {
constructor(props) { constructor(props) {
super(props); super(props);
this.state = { products }; this.state = { products, count: 0 };
} }
toggleInStock = () => { toggleInStock = () => {
@@ -163,17 +35,96 @@ class ProductList extends React.Component {
}; };
render() { render() {
const columns = [
{
dataField: 'id',
text: 'Product ID',
formatter: (cell, row, rowIndex, extraData) => (
<div>
<span>ID: {row.id}</span>
<br />
<span>state: {extraData}</span>
</div>
),
formatExtraData: this.state.count
},
{
dataField: 'name',
text: 'Product Name'
},
{
dataField: 'price',
text: 'Product Price'
},
{
dataField: 'inStock',
text: 'In Stock',
formatter: (cellContent, row) => (
<div className="checkbox disabled">
<label>
<input type="checkbox" checked={ row.inStock } disabled />
</label>
</div>
)
},
{
dataField: 'df1',
isDummyField: true,
text: 'Action 1',
formatter: (cellContent, row) => {
if (row.inStock) {
return (
<h5>
<span className="label label-success"> Available</span>
</h5>
);
}
return (
<h5>
<span className="label label-danger"> Backordered</span>
</h5>
);
}
},
{
dataField: 'df2',
isDummyField: true,
text: 'Action 2',
formatter: (cellContent, row) => {
if (row.inStock) {
return (
<h5>
<span className="label label-success"> Available</span>
</h5>
);
}
return (
<h5>
<span className="label label-danger"> Backordered</span>
</h5>
);
}
}
];
return ( return (
<div> <div>
<h1 className="h2">Products</h1> <h3>Action 1 and Action 2 are dummy column</h3>
<button onClick={ this.toggleInStock } className="btn btn-primary">
Toggle item 13 stock status
</button>
<button
className="btn btn-success"
onClick={ () => this.setState(() => ({ count: this.state.count + 1 })) }
>
Click me to Increase counter
</button>
<BootstrapTable <BootstrapTable
keyField="id" keyField="id"
data={ this.state.products } data={ this.state.products }
columns={ columns } columns={ columns }
/> />
<button onClick={ this.toggleInStock } className="btn btn-primary"> <Code>{ sourceCode }</Code>
Toggle item 13 stock status
</button>
</div> </div>
); );
} }
@@ -183,7 +134,7 @@ class ProductList extends React.Component {
class ProductList extends React.Component { class ProductList extends React.Component {
constructor(props) { constructor(props) {
super(props); super(props);
this.state = { products }; this.state = { products, count: 0 };
} }
toggleInStock = () => { toggleInStock = () => {
@@ -200,13 +151,95 @@ class ProductList extends React.Component {
this.setState(curr => ({ ...curr, products: newProducts })); this.setState(curr => ({ ...curr, products: newProducts }));
}; };
counter = () => {
this.setState(curr => ({ ...curr, count: this.state.count + 1 }));
}
render() { render() {
const columns = [
{
dataField: 'id',
text: 'Product ID',
formatter: (cell, row, rowIndex, extraData) => (
<div>
<span>ID: {row.id}</span>
<br />
<span>Counter: {extraData}</span>
</div>
),
formatExtraData: this.state.count
},
{
dataField: 'name',
text: 'Product Name'
},
{
dataField: 'price',
text: 'Product Price'
},
{
dataField: 'inStock',
text: 'In Stock',
formatter: (cellContent, row) => (
<div className="checkbox disabled">
<label>
<input type="checkbox" checked={ row.inStock } disabled />
</label>
</div>
)
},
{
dataField: 'df1',
isDummyField: true,
text: 'Action 1',
formatter: (cellContent, row) => {
if (row.inStock) {
return (
<h5>
<span className="label label-success"> Available</span>
</h5>
);
}
return (
<h5>
<span className="label label-danger"> Backordered</span>
</h5>
);
}
},
{
dataField: 'df2',
isDummyField: true,
text: 'Action 2',
formatter: (cellContent, row) => {
if (row.inStock) {
return (
<h5>
<span className="label label-success"> Available</span>
</h5>
);
}
return (
<h5>
<span className="label label-danger"> Backordered</span>
</h5>
);
}
}
];
return ( return (
<div> <div>
<h3>Action 1 and Action 2 are dummy column</h3> <h3>Action 1 and Action 2 are dummy column</h3>
<button onClick={ this.toggleInStock } className="btn btn-primary"> <button onClick={ this.toggleInStock } className="btn btn-primary">
Toggle item 13 stock status Toggle item 13 stock status
</button> </button>
<button
className="btn btn-success"
onClick={ this.counter }
>
Click me to Increase counter
</button>
<BootstrapTable <BootstrapTable
keyField="id" keyField="id"
data={ this.state.products } data={ this.state.products }

View File

@@ -0,0 +1,102 @@
/* eslint react/prop-types: 0 */
import React from 'react';
import BootstrapTable from 'react-bootstrap-table-next';
import ToolkitProvider, { CSVExport, Search } from 'react-bootstrap-table2-toolkit';
import filterFactory, { textFilter } from 'react-bootstrap-table2-filter';
import paginationFactory from 'react-bootstrap-table2-paginator';
import Code from 'components/common/code-block';
import { productsGenerator } from 'utils/common';
const { SearchBar } = Search;
const { ExportCSVButton } = CSVExport;
const products = productsGenerator(150);
const columns = [{
dataField: 'id',
text: 'Product ID'
}, {
dataField: 'name',
text: 'Product Name',
filter: textFilter()
}, {
dataField: 'price',
text: 'Product Price'
}];
const sourceCode = `\
import BootstrapTable from 'react-bootstrap-table-next';
import ToolkitProvider, { CSVExport, Search } from 'react-bootstrap-table2-toolkit';
import filterFactory, { textFilter } from 'react-bootstrap-table2-filter';
const { SearchBar } = Search;
const { ExportCSVButton } = CSVExport;
const columns = [{
dataField: 'id',
text: 'Product ID'
}, {
dataField: 'name',
text: 'Product Name'
}, {
dataField: 'price',
text: 'Product Price'
}];
const selectRow = {
mode: 'checkbox',
clickToSelect: true
};
<ToolkitProvider
keyField="id"
data={ products }
columns={ columns }
exportCSV={ { onlyExportFiltered: true, exportAll: false } }
search
>
{
props => (
<div>
<ExportCSVButton { ...props.csvProps }>Export CSV!!</ExportCSVButton>
<hr />
<SearchBar { ...props.searchProps } />
<BootstrapTable
{ ...props.baseProps }
pagination={ paginationFactory() }
filter={ filterFactory() }
/>
</div>
)
}
</ToolkitProvider>
`;
export default () => (
<div>
<h3>Export all the filtered/searched rows</h3>
<ToolkitProvider
keyField="id"
data={ products }
columns={ columns }
exportCSV={ { onlyExportFiltered: true, exportAll: false } }
search
>
{
props => (
<div>
<ExportCSVButton { ...props.csvProps }>Export CSV!!</ExportCSVButton>
<hr />
<SearchBar { ...props.searchProps } />
<BootstrapTable
{ ...props.baseProps }
pagination={ paginationFactory() }
filter={ filterFactory() }
/>
</div>
)
}
</ToolkitProvider>
<Code>{ sourceCode }</Code>
</div>
);

View File

@@ -1,6 +1,6 @@
{ {
"name": "react-bootstrap-table2-example", "name": "react-bootstrap-table2-example",
"version": "1.0.20", "version": "1.0.23",
"description": "", "description": "",
"main": "index.js", "main": "index.js",
"private": true, "private": true,

View File

@@ -192,6 +192,7 @@ import CSVFormatter from 'examples/csv/csv-column-formatter';
import CustomCSVHeader from 'examples/csv/custom-csv-header'; import CustomCSVHeader from 'examples/csv/custom-csv-header';
import HideCSVColumn from 'examples/csv/hide-column'; import HideCSVColumn from 'examples/csv/hide-column';
import ExportOnlySelected from 'examples/csv/export-only-selected'; import ExportOnlySelected from 'examples/csv/export-only-selected';
import ExportOnlyFiltered from 'examples/csv/export-only-filtered';
import CSVColumnType from 'examples/csv/csv-column-type'; import CSVColumnType from 'examples/csv/csv-column-type';
import CustomCSVButton from 'examples/csv/custom-csv-button'; import CustomCSVButton from 'examples/csv/custom-csv-button';
import ExportCustomData from 'examples/csv/export-custom-data'; import ExportCustomData from 'examples/csv/export-custom-data';
@@ -443,6 +444,7 @@ storiesOf('Export CSV', module)
.add('Custom CSV Header', () => <CustomCSVHeader />) .add('Custom CSV Header', () => <CustomCSVHeader />)
.add('Hide CSV Column', () => <HideCSVColumn />) .add('Hide CSV Column', () => <HideCSVColumn />)
.add('Only Export Selected Rows', () => <ExportOnlySelected />) .add('Only Export Selected Rows', () => <ExportOnlySelected />)
.add('Only Export Filtered/Searched Rows', () => <ExportOnlyFiltered />)
.add('CSV Column Type', () => <CSVColumnType />) .add('CSV Column Type', () => <CSVColumnType />)
.add('Custom CSV Button', () => <CustomCSVButton />) .add('Custom CSV Button', () => <CustomCSVButton />)
.add('Export Custom Data', () => <ExportCustomData />) .add('Export Custom Data', () => <ExportCustomData />)

View File

@@ -1,6 +1,6 @@
{ {
"name": "react-bootstrap-table2-filter", "name": "react-bootstrap-table2-filter",
"version": "1.1.6", "version": "1.1.8",
"description": "it's a column filter addon for react-bootstrap-table2", "description": "it's a column filter addon for react-bootstrap-table2",
"main": "./lib/index.js", "main": "./lib/index.js",
"repository": { "repository": {

View File

@@ -18,7 +18,7 @@ const legalComparators = [
]; ];
function dateParser(d) { function dateParser(d) {
return `${d.getFullYear()}-${('0' + (d.getMonth() + 1)).slice(-2)}-${('0' + d.getDate()).slice(-2)}`; return `${d.getUTCFullYear()}-${('0' + (d.getUTCMonth() + 1)).slice(-2)}-${('0' + d.getUTCDate()).slice(-2)}`;
} }
class DateFilter extends Component { class DateFilter extends Component {

View File

@@ -41,6 +41,8 @@ export default (
// let nextData = nextProps.data; // let nextData = nextProps.data;
if (!isRemoteFiltering() && !_.isEqual(nextProps.data, this.data)) { if (!isRemoteFiltering() && !_.isEqual(nextProps.data, this.data)) {
this.doFilter(nextProps, undefined, this.isEmitDataChange); this.doFilter(nextProps, undefined, this.isEmitDataChange);
} else {
this.data = nextProps.data;
} }
} }
@@ -89,6 +91,10 @@ export default (
}; };
} }
getFiltered() {
return this.data;
}
doFilter(props, customResult, ignoreEmitDataChange = false) { doFilter(props, customResult, ignoreEmitDataChange = false) {
let result = customResult; let result = customResult;

View File

@@ -98,9 +98,9 @@ export const filterByDate = _ => (
customFilterValue customFilterValue
) => { ) => {
if (!date || !comparator) return data; if (!date || !comparator) return data;
const filterDate = date.getDate(); const filterDate = date.getUTCDate();
const filterMonth = date.getMonth(); const filterMonth = date.getUTCMonth();
const filterYear = date.getFullYear(); const filterYear = date.getUTCFullYear();
return data.filter((row) => { return data.filter((row) => {
let valid = true; let valid = true;
@@ -114,9 +114,9 @@ export const filterByDate = _ => (
cell = new Date(cell); cell = new Date(cell);
} }
const targetDate = cell.getDate(); const targetDate = cell.getUTCDate();
const targetMonth = cell.getMonth(); const targetMonth = cell.getUTCMonth();
const targetYear = cell.getFullYear(); const targetYear = cell.getUTCFullYear();
switch (comparator) { switch (comparator) {

View File

@@ -1,6 +1,6 @@
{ {
"name": "react-bootstrap-table2-paginator", "name": "react-bootstrap-table2-paginator",
"version": "2.0.4", "version": "2.0.5",
"description": "it's the pagination addon for react-bootstrap-table2", "description": "it's the pagination addon for react-bootstrap-table2",
"main": "./lib/index.js", "main": "./lib/index.js",
"repository": { "repository": {

View File

@@ -56,7 +56,7 @@ export default ExtendBase =>
alwaysShowAllBtns alwaysShowAllBtns
} = this.props; } = this.props;
let pages; let pages = [];
let endPage = totalPages; let endPage = totalPages;
if (endPage <= 0) return []; if (endPage <= 0) return [];
@@ -68,24 +68,42 @@ export default ExtendBase =>
startPage = endPage - paginationSize + 1; startPage = endPage - paginationSize + 1;
} }
if (startPage !== pageStartIndex && totalPages > paginationSize && withFirstAndLast) { if (alwaysShowAllBtns) {
if (withFirstAndLast) {
pages = [firstPageText, prePageText]; pages = [firstPageText, prePageText];
} else if (totalPages > 1 || alwaysShowAllBtns) {
pages = [prePageText];
} else { } else {
pages = []; pages = [prePageText];
}
}
if (startPage !== pageStartIndex &&
totalPages > paginationSize &&
withFirstAndLast &&
pages.length === 0
) {
pages = [firstPageText, prePageText];
} else if (totalPages > 1 && pages.length === 0) {
pages = [prePageText];
} }
for (let i = startPage; i <= endPage; i += 1) { for (let i = startPage; i <= endPage; i += 1) {
if (i >= pageStartIndex) pages.push(i); if (i >= pageStartIndex) pages.push(i);
} }
if (endPage <= lastPage && pages.length > 1) { if (alwaysShowAllBtns || (endPage <= lastPage && pages.length > 1)) {
pages.push(nextPageText); pages.push(nextPageText);
} }
if (endPage !== lastPage && withFirstAndLast) { if ((endPage !== lastPage && withFirstAndLast) || (withFirstAndLast && alwaysShowAllBtns)) {
pages.push(lastPageText); pages.push(lastPageText);
} }
// if ((endPage <= lastPage && pages.length > 1) || alwaysShowAllBtns) {
// pages.push(nextPageText);
// }
// if (endPage !== lastPage && withFirstAndLast) {
// pages.push(lastPageText);
// }
return pages; return pages;
} }

View File

@@ -191,6 +191,11 @@ Default is `true`. `false` will only export current data which display on table.
#### onlyExportSelection - [bool] #### onlyExportSelection - [bool]
Default is `false`. `true` will only export the data which is selected. Default is `false`. `true` will only export the data which is selected.
#### onlyExportFiltered - [bool]
Default is `false`. `true` will only export the data which is filtered/searched.
>> When you configure this prop as true, you must turn off `exportAll`.
----- -----
## Column Toggle ## Column Toggle

View File

@@ -30,6 +30,7 @@ class ToolkitProvider extends statelessDecorator(React.Component) {
ignoreHeader: PropTypes.bool, ignoreHeader: PropTypes.bool,
noAutoBOM: PropTypes.bool, noAutoBOM: PropTypes.bool,
exportAll: PropTypes.bool, exportAll: PropTypes.bool,
onlyExportFiltered: PropTypes.bool,
onlyExportSelection: PropTypes.bool onlyExportSelection: PropTypes.bool
}) })
]) ])

View File

@@ -1,6 +1,6 @@
{ {
"name": "react-bootstrap-table2-toolkit", "name": "react-bootstrap-table2-toolkit",
"version": "1.3.2", "version": "1.4.0",
"description": "The toolkit for react-bootstrap-table2", "description": "The toolkit for react-bootstrap-table2",
"main": "./lib/index.js", "main": "./lib/index.js",
"repository": { "repository": {

View File

@@ -27,19 +27,24 @@ export default Base =>
data = source; data = source;
} else if (options.exportAll) { } else if (options.exportAll) {
data = this.props.data; data = this.props.data;
} else if (options.onlyExportFiltered) {
const payload = {};
this.tableExposedAPIEmitter.emit('get.filtered.rows', payload);
data = payload.result;
} else { } else {
const payload = {}; const payload = {};
this.tableExposedAPIEmitter.emit('get.table.data', payload); this.tableExposedAPIEmitter.emit('get.table.data', payload);
data = payload.result; data = payload.result;
} }
// filter data // filter data by row selection
if (options.onlyExportSelection) { if (options.onlyExportSelection) {
const payload = {}; const payload = {};
this.tableExposedAPIEmitter.emit('get.selected.rows', payload); this.tableExposedAPIEmitter.emit('get.selected.rows', payload);
const selections = payload.result; const selections = payload.result;
data = data.filter(row => !!selections.find(sel => row[keyField] === sel)); data = data.filter(row => !!selections.find(sel => row[keyField] === sel));
} }
const content = transform(data, meta, this._.get, options); const content = transform(data, meta, this._.get, options);
save(content, options); save(content, options);
} }

View File

@@ -59,6 +59,10 @@ export default (options = {
} }
} }
getSearched() {
return this.state.data;
}
triggerListener(result) { triggerListener(result) {
if (this.props.dataChangeListener) { if (this.props.dataChangeListener) {
this.props.dataChangeListener.emit('filterChanged', result.length); this.props.dataChangeListener.emit('filterChanged', result.length);

View File

@@ -1,6 +1,6 @@
{ {
"name": "react-bootstrap-table-next", "name": "react-bootstrap-table-next",
"version": "3.0.1", "version": "3.1.0",
"description": "Next generation of react-bootstrap-table", "description": "Next generation of react-bootstrap-table",
"main": "./lib/index.js", "main": "./lib/index.js",
"repository": { "repository": {
@@ -37,6 +37,7 @@
], ],
"dependencies": { "dependencies": {
"classnames": "2.2.5", "classnames": "2.2.5",
"react-transition-group": "2.5.3",
"underscore": "1.9.1" "underscore": "1.9.1"
}, },
"peerDependencies": { "peerDependencies": {

View File

@@ -26,7 +26,7 @@ class Cell extends eventDelegater(Component) {
// if (nextProps.formatter) // if (nextProps.formatter)
shouldUpdate = shouldUpdate =
nextProps.column.formatter ? !_.isEqual(this.props.row, nextProps.row) : false || (nextProps.column.formatter ? !_.isEqual(this.props.row, nextProps.row) : false) ||
this.props.column.hidden !== nextProps.column.hidden || this.props.column.hidden !== nextProps.column.hidden ||
this.props.rowIndex !== nextProps.rowIndex || this.props.rowIndex !== nextProps.rowIndex ||
this.props.columnIndex !== nextProps.columnIndex || this.props.columnIndex !== nextProps.columnIndex ||

View File

@@ -23,6 +23,15 @@ const withContext = Base =>
const exposedAPIEmitter = new EventEmitter(); const exposedAPIEmitter = new EventEmitter();
exposedAPIEmitter.on('get.table.data', payload => payload.result = this.table.getData()); exposedAPIEmitter.on('get.table.data', payload => payload.result = this.table.getData());
exposedAPIEmitter.on('get.selected.rows', payload => payload.result = this.selectionContext.getSelected()); exposedAPIEmitter.on('get.selected.rows', payload => payload.result = this.selectionContext.getSelected());
exposedAPIEmitter.on('get.filtered.rows', (payload) => {
if (this.searchContext) {
payload.result = this.searchContext.getSearched();
} else if (this.filterContext) {
payload.result = this.filterContext.getFiltered();
} else {
payload.result = this.table.getData();
}
});
props.registerExposedAPI(exposedAPIEmitter); props.registerExposedAPI(exposedAPIEmitter);
} }

View File

@@ -10,18 +10,31 @@ class RowExpandProvider extends React.Component {
children: PropTypes.node.isRequired, children: PropTypes.node.isRequired,
data: PropTypes.array.isRequired, data: PropTypes.array.isRequired,
keyField: PropTypes.string.isRequired keyField: PropTypes.string.isRequired
} };
state = { expanded: this.props.expandRow.expanded || [] }; state = { expanded: this.props.expandRow.expanded || [],
isClosing: this.props.expandRow.isClosing || [] };
componentWillReceiveProps(nextProps) { componentWillReceiveProps(nextProps) {
if (nextProps.expandRow) { if (nextProps.expandRow) {
const isClosing = this.state.expanded.reduce((acc, cur) => {
if (!nextProps.expandRow.expanded.includes(cur)) {
acc.push(cur);
}
return acc;
}, []);
this.setState(() => ({ expanded: nextProps.expandRow.expanded, isClosing }));
} else {
this.setState(() => ({ this.setState(() => ({
expanded: nextProps.expandRow.expanded || this.state.expanded expanded: this.state.expanded
})); }));
} }
} }
onClosed = (closedRow) => {
this.setState({ isClosing: this.state.isClosing.filter(value => value !== closedRow) });
};
handleRowExpand = (rowKey, expanded, rowIndex, e) => { handleRowExpand = (rowKey, expanded, rowIndex, e) => {
const { data, keyField, expandRow: { onExpand, onlyOneExpanding, nonExpandable } } = this.props; const { data, keyField, expandRow: { onExpand, onlyOneExpanding, nonExpandable } } = this.props;
if (nonExpandable && nonExpandable.includes(rowKey)) { if (nonExpandable && nonExpandable.includes(rowKey)) {
@@ -29,11 +42,15 @@ class RowExpandProvider extends React.Component {
} }
let currExpanded = [...this.state.expanded]; let currExpanded = [...this.state.expanded];
let isClosing = [...this.state.isClosing];
if (expanded) { if (expanded) {
if (onlyOneExpanding) currExpanded = [rowKey]; if (onlyOneExpanding) {
else currExpanded.push(rowKey); isClosing = isClosing.concat(currExpanded);
currExpanded = [rowKey];
} else currExpanded.push(rowKey);
} else { } else {
isClosing.push(rowKey);
currExpanded = currExpanded.filter(value => value !== rowKey); currExpanded = currExpanded.filter(value => value !== rowKey);
} }
@@ -41,8 +58,8 @@ class RowExpandProvider extends React.Component {
const row = dataOperator.getRowByRowId(data, keyField, rowKey); const row = dataOperator.getRowByRowId(data, keyField, rowKey);
onExpand(row, expanded, rowIndex, e); onExpand(row, expanded, rowIndex, e);
} }
this.setState(() => ({ expanded: currExpanded })); this.setState(() => ({ expanded: currExpanded, isClosing }));
} };
handleAllRowExpand = (e, expandAll) => { handleAllRowExpand = (e, expandAll) => {
const { const {
@@ -68,7 +85,7 @@ class RowExpandProvider extends React.Component {
} }
this.setState(() => ({ expanded: currExpanded })); this.setState(() => ({ expanded: currExpanded }));
} };
render() { render() {
const { data, keyField } = this.props; const { data, keyField } = this.props;
@@ -78,6 +95,8 @@ class RowExpandProvider extends React.Component {
...this.props.expandRow, ...this.props.expandRow,
nonExpandable: this.props.expandRow.nonExpandable, nonExpandable: this.props.expandRow.nonExpandable,
expanded: this.state.expanded, expanded: this.state.expanded,
isClosing: this.state.isClosing,
onClosed: this.onClosed,
isAnyExpands: dataOperator.isAnyExpands(data, keyField, this.state.expanded), isAnyExpands: dataOperator.isAnyExpands(data, keyField, this.state.expanded),
onRowExpand: this.handleRowExpand, onRowExpand: this.handleRowExpand,
onAllRowExpand: this.handleAllRowExpand onAllRowExpand: this.handleAllRowExpand

View File

@@ -1,18 +1,37 @@
import React from 'react'; import React from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { CSSTransition } from 'react-transition-group';
const ExpandRow = ({ children, ...rest }) => ( const ExpandRow = ({ children, expanded, onClosed, ...rest }) => (
<tr className="expanding-row"> <tr>
<td { ...rest }>{ children }</td> <td className="reset-expansion-style" { ...rest }>
<CSSTransition
appear
in={ expanded }
timeout={ 400 }
classNames="row-expand-slide"
onExited={ onClosed }
>
<div>
<div className="row-expansion-style">
{ children }
</div>
</div>
</CSSTransition>
</td>
</tr> </tr>
); );
ExpandRow.propTypes = { ExpandRow.propTypes = {
children: PropTypes.node children: PropTypes.node,
expanded: PropTypes.bool,
onClosed: PropTypes.func
}; };
ExpandRow.defaultProps = { ExpandRow.defaultProps = {
children: null children: null,
expanded: false,
onClosed: null
}; };
export default ExpandRow; export default ExpandRow;

View File

@@ -8,8 +8,8 @@ export default (Component) => {
const key = props.value; const key = props.value;
const expanded = expandRow.expanded.includes(key); const expanded = expandRow.expanded.includes(key);
const isClosing = expandRow.isClosing.includes(key);
const expandable = !expandRow.nonExpandable || !expandRow.nonExpandable.includes(key); const expandable = !expandRow.nonExpandable || !expandRow.nonExpandable.includes(key);
return [ return [
<Component <Component
{ ...props } { ...props }
@@ -18,9 +18,11 @@ export default (Component) => {
expandable={ expandable } expandable={ expandable }
expandRow={ { ...expandRow } } expandRow={ { ...expandRow } }
/>, />,
expanded ? <ExpandRow expanded || isClosing ? <ExpandRow
key={ `${key}-expanding` } key={ `${key}-expanding` }
colSpan={ props.visibleColumnSize } colSpan={ props.visibleColumnSize }
expanded={ expanded }
onClosed={ () => expandRow.onClosed(key) }
> >
{ expandRow.renderer(props.row) } { expandRow.renderer(props.row) }
</ExpandRow> : null </ExpandRow> : null

View File

@@ -8,7 +8,8 @@ export default ExtendBase =>
return ( return (
nextProps.editingRowIdx === nextProps.rowIndex || nextProps.editingRowIdx === nextProps.rowIndex ||
(this.props.editingRowIdx === nextProps.rowIndex && (this.props.editingRowIdx === nextProps.rowIndex &&
nextProps.editingRowIdx === null) nextProps.editingRowIdx === null) ||
this.props.editingRowIdx === nextProps.rowIndex
); );
} }
@@ -26,7 +27,7 @@ export default ExtendBase =>
return true; return true;
} }
for (let i = 0; i < this.props.columns.length; i += 1) { for (let i = 0; i < this.props.columns.length; i += 1) {
if (this.props.columns[i].hidden !== nextProps.columns[i].hidden) { if (!_.isEqual(this.props.columns[i], nextProps.columns[i])) {
return true; return true;
} }
} }

View File

@@ -68,10 +68,6 @@
text-align: center; text-align: center;
} }
tr.expanding-row {
padding: 5px;
}
td.react-bootstrap-table-editing-cell { td.react-bootstrap-table-editing-cell {
.animated { .animated {
animation-fill-mode: both; animation-fill-mode: both;
@@ -161,4 +157,26 @@
animation-name: bounceOut; animation-name: bounceOut;
} }
} }
.reset-expansion-style{
padding: 0;
}
.row-expansion-style{
padding: 8px;
}
.row-expand-slide-appear{
max-height: 0;
overflow: hidden;
}
.row-expand-slide-appear-active{
max-height: 1000px;
transition: max-height 3s linear;
}
.row-expand-slide-exit{
max-height: 1000px;
}
.row-expand-slide-exit-active{
max-height: 0;
overflow: hidden;
transition: max-height 400ms cubic-bezier(0, 0.95, 0, 0.95)
}
} }