mirror of
https://github.com/gosticks/react-bootstrap-table2.git
synced 2025-10-16 11:55:39 +00:00
Add table footer
This commit is contained in:
parent
416fcf08d4
commit
bd2ce5abf0
52
packages/react-bootstrap-table2-example/examples/footer/column-align-table.js
vendored
Normal file
52
packages/react-bootstrap-table2-example/examples/footer/column-align-table.js
vendored
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
/* eslint no-unused-vars: 0 */
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
import BootstrapTable from 'react-bootstrap-table-next';
|
||||||
|
import Code from 'components/common/code-block';
|
||||||
|
import { productsGenerator } from 'utils/common';
|
||||||
|
|
||||||
|
const products = productsGenerator();
|
||||||
|
|
||||||
|
const columns = [{
|
||||||
|
dataField: 'id',
|
||||||
|
text: 'Product ID',
|
||||||
|
footerAlign: 'center',
|
||||||
|
footer: 'Footer 1'
|
||||||
|
}, {
|
||||||
|
dataField: 'name',
|
||||||
|
text: 'Product Name',
|
||||||
|
footerAlign: (column, colIndex) => 'right',
|
||||||
|
footer: 'Footer 2'
|
||||||
|
}, {
|
||||||
|
dataField: 'price',
|
||||||
|
text: 'Product Price',
|
||||||
|
footer: 'Footer 3'
|
||||||
|
}];
|
||||||
|
|
||||||
|
const sourceCode = `\
|
||||||
|
import BootstrapTable from 'react-bootstrap-table-next';
|
||||||
|
|
||||||
|
const columns = [{
|
||||||
|
dataField: 'id',
|
||||||
|
text: 'Product ID',
|
||||||
|
footerAlign: 'center',
|
||||||
|
footer: 'Footer 1'
|
||||||
|
}, {
|
||||||
|
dataField: 'name',
|
||||||
|
text: 'Product Name',
|
||||||
|
footerAlign: (column, colIndex) => 'right',
|
||||||
|
footer: 'Footer 2'
|
||||||
|
}, {
|
||||||
|
dataField: 'price',
|
||||||
|
text: 'Product Price'
|
||||||
|
}];
|
||||||
|
|
||||||
|
<BootstrapTable keyField='id' data={ products } columns={ columns } />
|
||||||
|
`;
|
||||||
|
|
||||||
|
export default () => (
|
||||||
|
<div>
|
||||||
|
<BootstrapTable keyField="id" data={ products } columns={ columns } />
|
||||||
|
<Code>{ sourceCode }</Code>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
67
packages/react-bootstrap-table2-example/examples/footer/column-format-table.js
vendored
Normal file
67
packages/react-bootstrap-table2-example/examples/footer/column-format-table.js
vendored
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
/* eslint no-unused-vars: 0 */
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
import BootstrapTable from 'react-bootstrap-table-next';
|
||||||
|
import Code from 'components/common/code-block';
|
||||||
|
import { productsGenerator } from 'utils/common';
|
||||||
|
|
||||||
|
const products = productsGenerator();
|
||||||
|
|
||||||
|
function priceFormatter(column, colIndex) {
|
||||||
|
return (
|
||||||
|
<h5>
|
||||||
|
<strong>$$ {column.text} $$</strong>
|
||||||
|
</h5>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const columns = [
|
||||||
|
{
|
||||||
|
dataField: 'id',
|
||||||
|
text: 'Product ID',
|
||||||
|
footer: 'Footer 1'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
dataField: 'name',
|
||||||
|
text: 'Product Name',
|
||||||
|
footer: 'Footer 2'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
dataField: 'price',
|
||||||
|
text: 'Product Price',
|
||||||
|
footer: 'Footer 3',
|
||||||
|
footerFormatter: priceFormatter
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
const sourceCode = `\
|
||||||
|
import BootstrapTable from 'react-bootstrap-table-next';
|
||||||
|
|
||||||
|
function priceFormatter(column, colIndex) {
|
||||||
|
return (
|
||||||
|
<h5><strong>$$ { column.text } $$</strong></h5>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const columns = [
|
||||||
|
// omit...
|
||||||
|
{
|
||||||
|
dataField: 'price',
|
||||||
|
text: 'Product Price',
|
||||||
|
footer: 'Footer 3',
|
||||||
|
footerFormatter: priceFormatter
|
||||||
|
}];
|
||||||
|
|
||||||
|
<BootstrapTable
|
||||||
|
keyField="id"
|
||||||
|
data={ products }
|
||||||
|
columns={ columns }
|
||||||
|
/>
|
||||||
|
`;
|
||||||
|
|
||||||
|
export default () => (
|
||||||
|
<div>
|
||||||
|
<BootstrapTable keyField="id" data={ products } columns={ columns } />
|
||||||
|
<Code>{sourceCode}</Code>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
61
packages/react-bootstrap-table2-example/examples/footer/footer-class-table.js
vendored
Normal file
61
packages/react-bootstrap-table2-example/examples/footer/footer-class-table.js
vendored
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
import BootstrapTable from 'react-bootstrap-table-next';
|
||||||
|
import Code from 'components/common/code-block';
|
||||||
|
import { productsGenerator } from 'utils/common';
|
||||||
|
|
||||||
|
const products = productsGenerator();
|
||||||
|
|
||||||
|
const columns = [
|
||||||
|
{
|
||||||
|
dataField: 'id',
|
||||||
|
text: 'Product ID',
|
||||||
|
footer: 'Footer 1'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
dataField: 'name',
|
||||||
|
text: 'Product Name',
|
||||||
|
footer: 'Footer 2'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
dataField: 'price',
|
||||||
|
text: 'Product Price',
|
||||||
|
footer: 'Footer 3'
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
const sourceCode = `\
|
||||||
|
import BootstrapTable from 'react-bootstrap-table-next';
|
||||||
|
|
||||||
|
const columns = [
|
||||||
|
{
|
||||||
|
dataField: 'id',
|
||||||
|
text: 'Product ID',
|
||||||
|
footer: 'Footer 1'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
dataField: 'name',
|
||||||
|
text: 'Product Name',
|
||||||
|
footer: 'Footer 2'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
dataField: 'price',
|
||||||
|
text: 'Product Price',
|
||||||
|
footer: 'Footer 3'
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
<BootstrapTable
|
||||||
|
keyField="id"
|
||||||
|
data={ products }
|
||||||
|
columns={ columns }
|
||||||
|
footerClasses="footer-class"
|
||||||
|
/>
|
||||||
|
`;
|
||||||
|
|
||||||
|
export default () => (
|
||||||
|
<div>
|
||||||
|
<BootstrapTable keyField="id" data={ products } columns={ columns } footerClasses="footer-class" />
|
||||||
|
<Code>{sourceCode}</Code>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
52
packages/react-bootstrap-table2-example/examples/footer/function-footer.js
vendored
Normal file
52
packages/react-bootstrap-table2-example/examples/footer/function-footer.js
vendored
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
/* eslint no-unused-vars: 0 */
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
import BootstrapTable from 'react-bootstrap-table-next';
|
||||||
|
import Code from 'components/common/code-block';
|
||||||
|
|
||||||
|
import { productsGenerator } from 'utils/common';
|
||||||
|
|
||||||
|
const products = productsGenerator();
|
||||||
|
|
||||||
|
const columns = [
|
||||||
|
{
|
||||||
|
dataField: 'id',
|
||||||
|
text: 'Product ID',
|
||||||
|
footer: 'Footer 1'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
dataField: 'name',
|
||||||
|
text: 'Product Name',
|
||||||
|
footer: 'Footer 2'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
dataField: 'price',
|
||||||
|
text: 'Product Price',
|
||||||
|
footer: columnData => columnData.reduce((acc, item) => acc + item, 0)
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
const sourceCode = `\
|
||||||
|
import BootstrapTable from 'react-bootstrap-table-next';
|
||||||
|
|
||||||
|
const columns = [
|
||||||
|
// omit...
|
||||||
|
{
|
||||||
|
dataField: 'price',
|
||||||
|
text: 'Product Price',
|
||||||
|
footer: columnData => columnData.reduce((acc, item) => acc + item, 0)
|
||||||
|
}];
|
||||||
|
|
||||||
|
<BootstrapTable
|
||||||
|
keyField="id"
|
||||||
|
data={ products }
|
||||||
|
columns={ columns }
|
||||||
|
/>
|
||||||
|
`;
|
||||||
|
|
||||||
|
export default () => (
|
||||||
|
<div>
|
||||||
|
<BootstrapTable keyField="id" data={ products } columns={ columns } />
|
||||||
|
<Code>{sourceCode}</Code>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
52
packages/react-bootstrap-table2-example/examples/footer/simple-footer.js
vendored
Normal file
52
packages/react-bootstrap-table2-example/examples/footer/simple-footer.js
vendored
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
/* eslint no-unused-vars: 0 */
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
import BootstrapTable from 'react-bootstrap-table-next';
|
||||||
|
import Code from 'components/common/code-block';
|
||||||
|
|
||||||
|
import { productsGenerator } from 'utils/common';
|
||||||
|
|
||||||
|
const products = productsGenerator();
|
||||||
|
|
||||||
|
const columns = [
|
||||||
|
{
|
||||||
|
dataField: 'id',
|
||||||
|
text: 'Product ID',
|
||||||
|
footer: 'Footer 1'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
dataField: 'name',
|
||||||
|
text: 'Product Name',
|
||||||
|
footer: 'Footer 2'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
dataField: 'price',
|
||||||
|
text: 'Product Price',
|
||||||
|
footer: 'Footer 3'
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
const sourceCode = `\
|
||||||
|
import BootstrapTable from 'react-bootstrap-table-next';
|
||||||
|
|
||||||
|
const columns = [
|
||||||
|
// omit...
|
||||||
|
{
|
||||||
|
dataField: 'price',
|
||||||
|
text: 'Product Price',
|
||||||
|
footer: 'Footer 3'
|
||||||
|
}];
|
||||||
|
|
||||||
|
<BootstrapTable
|
||||||
|
keyField="id"
|
||||||
|
data={ products }
|
||||||
|
columns={ columns }
|
||||||
|
/>
|
||||||
|
`;
|
||||||
|
|
||||||
|
export default () => (
|
||||||
|
<div>
|
||||||
|
<BootstrapTable keyField="id" data={ products } columns={ columns } />
|
||||||
|
<Code>{sourceCode}</Code>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
@ -45,6 +45,13 @@ import HeaderColumnStyleTable from 'examples/header-columns/column-style-table';
|
|||||||
import HeaderColumnAttrsTable from 'examples/header-columns/column-attrs-table';
|
import HeaderColumnAttrsTable from 'examples/header-columns/column-attrs-table';
|
||||||
import HeaderClassTable from 'examples/header-columns/header-class-table';
|
import HeaderClassTable from 'examples/header-columns/header-class-table';
|
||||||
|
|
||||||
|
// footer
|
||||||
|
import SimpleFooter from 'examples/footer/simple-footer';
|
||||||
|
import FunctionFooter from 'examples/footer/function-footer';
|
||||||
|
import FooterClassTable from 'examples/footer/footer-class-table';
|
||||||
|
import FooterColumnFormatTable from 'examples/footer/column-format-table';
|
||||||
|
import FooterColumnAlignTable from 'examples/footer/column-align-table';
|
||||||
|
|
||||||
// column filter
|
// column filter
|
||||||
import TextFilter from 'examples/column-filter/text-filter';
|
import TextFilter from 'examples/column-filter/text-filter';
|
||||||
import TextFilterWithDefaultValue from 'examples/column-filter/text-filter-default-value';
|
import TextFilterWithDefaultValue from 'examples/column-filter/text-filter-default-value';
|
||||||
@ -199,8 +206,7 @@ import '../../react-bootstrap-table2-filter/style/react-bootstrap-table2-filter.
|
|||||||
// import bootstrap style by given version
|
// import bootstrap style by given version
|
||||||
import bootstrapStyle, { BOOTSTRAP_VERSION } from './bootstrap-style';
|
import bootstrapStyle, { BOOTSTRAP_VERSION } from './bootstrap-style';
|
||||||
|
|
||||||
storiesOf('Welcome', module)
|
storiesOf('Welcome', module).add('react bootstrap table 2 ', () => <Welcome />);
|
||||||
.add('react bootstrap table 2 ', () => <Welcome />);
|
|
||||||
|
|
||||||
storiesOf('Basic Table', module)
|
storiesOf('Basic Table', module)
|
||||||
.addDecorator(bootstrapStyle())
|
.addDecorator(bootstrapStyle())
|
||||||
@ -286,6 +292,14 @@ storiesOf('Work on Rows', module)
|
|||||||
.add('Hide Rows', () => <RowHiddenTable />)
|
.add('Hide Rows', () => <RowHiddenTable />)
|
||||||
.add('Row Event', () => <RowEventTable />);
|
.add('Row Event', () => <RowEventTable />);
|
||||||
|
|
||||||
|
storiesOf('Footer', module)
|
||||||
|
.addDecorator(bootstrapStyle())
|
||||||
|
.add('Simple Footer', () => <SimpleFooter />)
|
||||||
|
.add('Function Footer', () => <FunctionFooter />)
|
||||||
|
.add('Footer Class', () => <FooterClassTable />)
|
||||||
|
.add('Column Formatter', () => <FooterColumnFormatTable />)
|
||||||
|
.add('Column Align', () => <FooterColumnAlignTable />);
|
||||||
|
|
||||||
storiesOf('Sort Table', module)
|
storiesOf('Sort Table', module)
|
||||||
.addDecorator(bootstrapStyle())
|
.addDecorator(bootstrapStyle())
|
||||||
.add('Enable Sort', () => <EnableSortTable />)
|
.add('Enable Sort', () => <EnableSortTable />)
|
||||||
|
|||||||
@ -11,6 +11,10 @@
|
|||||||
background-color: $green-lighten-4;
|
background-color: $green-lighten-4;
|
||||||
}
|
}
|
||||||
|
|
||||||
.header-class {
|
thead .header-class {
|
||||||
|
background-color: $green-lighten-4;
|
||||||
|
}
|
||||||
|
|
||||||
|
tfoot .footer-class {
|
||||||
background-color: $green-lighten-4;
|
background-color: $green-lighten-4;
|
||||||
}
|
}
|
||||||
@ -7,8 +7,10 @@ import cs from 'classnames';
|
|||||||
import Header from './header';
|
import Header from './header';
|
||||||
import Caption from './caption';
|
import Caption from './caption';
|
||||||
import Body from './body';
|
import Body from './body';
|
||||||
|
import Footer from './footer';
|
||||||
import PropsBaseResolver from './props-resolver';
|
import PropsBaseResolver from './props-resolver';
|
||||||
import Const from './const';
|
import Const from './const';
|
||||||
|
import _ from './utils';
|
||||||
|
|
||||||
class BootstrapTable extends PropsBaseResolver(Component) {
|
class BootstrapTable extends PropsBaseResolver(Component) {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
@ -25,11 +27,7 @@ class BootstrapTable extends PropsBaseResolver(Component) {
|
|||||||
const { loading, overlay } = this.props;
|
const { loading, overlay } = this.props;
|
||||||
if (overlay) {
|
if (overlay) {
|
||||||
const LoadingOverlay = overlay(loading);
|
const LoadingOverlay = overlay(loading);
|
||||||
return (
|
return <LoadingOverlay>{this.renderTable()}</LoadingOverlay>;
|
||||||
<LoadingOverlay>
|
|
||||||
{ this.renderTable() }
|
|
||||||
</LoadingOverlay>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
return this.renderTable();
|
return this.renderTable();
|
||||||
}
|
}
|
||||||
@ -59,19 +57,25 @@ class BootstrapTable extends PropsBaseResolver(Component) {
|
|||||||
|
|
||||||
const tableWrapperClass = cs('react-bootstrap-table', wrapperClasses);
|
const tableWrapperClass = cs('react-bootstrap-table', wrapperClasses);
|
||||||
|
|
||||||
const tableClass = cs('table', {
|
const tableClass = cs(
|
||||||
'table-striped': striped,
|
'table',
|
||||||
'table-hover': hover,
|
{
|
||||||
'table-bordered': bordered,
|
'table-striped': striped,
|
||||||
[(bootstrap4 ? 'table-sm' : 'table-condensed')]: condensed
|
'table-hover': hover,
|
||||||
}, classes);
|
'table-bordered': bordered,
|
||||||
|
[bootstrap4 ? 'table-sm' : 'table-condensed']: condensed
|
||||||
|
},
|
||||||
|
classes
|
||||||
|
);
|
||||||
|
|
||||||
const tableCaption = (caption && <Caption>{ caption }</Caption>);
|
const hasFooter = _.filter(columns, col => _.has(col, 'footer')).length > 0;
|
||||||
|
|
||||||
|
const tableCaption = caption && <Caption>{caption}</Caption>;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={ tableWrapperClass }>
|
<div className={ tableWrapperClass }>
|
||||||
<table id={ id } className={ tableClass }>
|
<table id={ id } className={ tableClass }>
|
||||||
{ tableCaption }
|
{tableCaption}
|
||||||
<Header
|
<Header
|
||||||
columns={ columns }
|
columns={ columns }
|
||||||
className={ this.props.headerClasses }
|
className={ this.props.headerClasses }
|
||||||
@ -98,6 +102,9 @@ class BootstrapTable extends PropsBaseResolver(Component) {
|
|||||||
rowClasses={ rowClasses }
|
rowClasses={ rowClasses }
|
||||||
rowEvents={ rowEvents }
|
rowEvents={ rowEvents }
|
||||||
/>
|
/>
|
||||||
|
{hasFooter && (
|
||||||
|
<Footer data={ data } columns={ columns } className={ this.props.footerClasses } />
|
||||||
|
)}
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
@ -109,9 +116,12 @@ BootstrapTable.propTypes = {
|
|||||||
data: PropTypes.array.isRequired,
|
data: PropTypes.array.isRequired,
|
||||||
columns: PropTypes.array.isRequired,
|
columns: PropTypes.array.isRequired,
|
||||||
bootstrap4: PropTypes.bool,
|
bootstrap4: PropTypes.bool,
|
||||||
remote: PropTypes.oneOfType([PropTypes.bool, PropTypes.shape({
|
remote: PropTypes.oneOfType([
|
||||||
pagination: PropTypes.bool
|
PropTypes.bool,
|
||||||
})]),
|
PropTypes.shape({
|
||||||
|
pagination: PropTypes.bool
|
||||||
|
})
|
||||||
|
]),
|
||||||
noDataIndication: PropTypes.oneOfType([PropTypes.string, PropTypes.func]),
|
noDataIndication: PropTypes.oneOfType([PropTypes.string, PropTypes.func]),
|
||||||
striped: PropTypes.bool,
|
striped: PropTypes.bool,
|
||||||
bordered: PropTypes.bool,
|
bordered: PropTypes.bool,
|
||||||
@ -121,10 +131,7 @@ BootstrapTable.propTypes = {
|
|||||||
classes: PropTypes.string,
|
classes: PropTypes.string,
|
||||||
wrapperClasses: PropTypes.string,
|
wrapperClasses: PropTypes.string,
|
||||||
condensed: PropTypes.bool,
|
condensed: PropTypes.bool,
|
||||||
caption: PropTypes.oneOfType([
|
caption: PropTypes.oneOfType([PropTypes.node, PropTypes.string]),
|
||||||
PropTypes.node,
|
|
||||||
PropTypes.string
|
|
||||||
]),
|
|
||||||
pagination: PropTypes.object,
|
pagination: PropTypes.object,
|
||||||
filter: PropTypes.object,
|
filter: PropTypes.object,
|
||||||
cellEdit: PropTypes.object,
|
cellEdit: PropTypes.object,
|
||||||
@ -168,10 +175,13 @@ BootstrapTable.propTypes = {
|
|||||||
rowEvents: PropTypes.object,
|
rowEvents: PropTypes.object,
|
||||||
rowClasses: PropTypes.oneOfType([PropTypes.string, PropTypes.func]),
|
rowClasses: PropTypes.oneOfType([PropTypes.string, PropTypes.func]),
|
||||||
headerClasses: PropTypes.string,
|
headerClasses: PropTypes.string,
|
||||||
defaultSorted: PropTypes.arrayOf(PropTypes.shape({
|
footerClasses: PropTypes.string,
|
||||||
dataField: PropTypes.string.isRequired,
|
defaultSorted: PropTypes.arrayOf(
|
||||||
order: PropTypes.oneOf([Const.SORT_DESC, Const.SORT_ASC]).isRequired
|
PropTypes.shape({
|
||||||
})),
|
dataField: PropTypes.string.isRequired,
|
||||||
|
order: PropTypes.oneOf([Const.SORT_DESC, Const.SORT_ASC]).isRequired
|
||||||
|
})
|
||||||
|
),
|
||||||
defaultSortDirection: PropTypes.oneOf([Const.SORT_DESC, Const.SORT_ASC]),
|
defaultSortDirection: PropTypes.oneOf([Const.SORT_DESC, Const.SORT_ASC]),
|
||||||
overlay: PropTypes.func,
|
overlay: PropTypes.func,
|
||||||
onTableChange: PropTypes.func,
|
onTableChange: PropTypes.func,
|
||||||
|
|||||||
64
packages/react-bootstrap-table2/src/footer-cell.js
vendored
Normal file
64
packages/react-bootstrap-table2/src/footer-cell.js
vendored
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
/* eslint react/require-default-props: 0 */
|
||||||
|
import React from 'react';
|
||||||
|
import cs from 'classnames';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
|
||||||
|
import _ from './utils';
|
||||||
|
|
||||||
|
const FooterCell = (props) => {
|
||||||
|
const { index, column, columnData } = props;
|
||||||
|
|
||||||
|
const {
|
||||||
|
footer,
|
||||||
|
footerTitle,
|
||||||
|
footerAlign,
|
||||||
|
footerFormatter,
|
||||||
|
footerEvents,
|
||||||
|
footerClasses,
|
||||||
|
footerStyle,
|
||||||
|
footerAttrs
|
||||||
|
} = column;
|
||||||
|
|
||||||
|
const cellAttrs = {
|
||||||
|
...(_.isFunction(footerAttrs) ? footerAttrs(column, index) : footerAttrs),
|
||||||
|
...footerEvents
|
||||||
|
};
|
||||||
|
|
||||||
|
let text = '';
|
||||||
|
if (_.isString(footer)) {
|
||||||
|
text = footer;
|
||||||
|
} else if (_.isFunction(footer)) {
|
||||||
|
text = footer(columnData, column, index);
|
||||||
|
}
|
||||||
|
|
||||||
|
let cellStyle = {};
|
||||||
|
const cellClasses = _.isFunction(footerClasses) ? footerClasses(column, index) : footerClasses;
|
||||||
|
|
||||||
|
if (footerStyle) {
|
||||||
|
cellStyle = _.isFunction(footerStyle) ? footerStyle(column, index) : footerStyle;
|
||||||
|
cellStyle = cellStyle ? { ...cellStyle } : cellStyle;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (footerTitle) {
|
||||||
|
cellAttrs.title = _.isFunction(footerTitle) ? footerTitle(column, index) : text;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (footerAlign) {
|
||||||
|
cellStyle.textAlign = _.isFunction(footerAlign) ? footerAlign(column, index) : footerAlign;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cellClasses) cellAttrs.className = cs(cellAttrs.className, cellClasses);
|
||||||
|
if (!_.isEmptyObject(cellStyle)) cellAttrs.style = cellStyle;
|
||||||
|
|
||||||
|
const children = footerFormatter ? footerFormatter(column, index) : text;
|
||||||
|
|
||||||
|
return React.createElement('th', cellAttrs, children);
|
||||||
|
};
|
||||||
|
|
||||||
|
FooterCell.propTypes = {
|
||||||
|
columnData: PropTypes.array,
|
||||||
|
index: PropTypes.number,
|
||||||
|
column: PropTypes.object
|
||||||
|
};
|
||||||
|
|
||||||
|
export default FooterCell;
|
||||||
41
packages/react-bootstrap-table2/src/footer.js
vendored
Normal file
41
packages/react-bootstrap-table2/src/footer.js
vendored
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
/* eslint react/require-default-props: 0 */
|
||||||
|
import React from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
|
||||||
|
import FooterCell from './footer-cell';
|
||||||
|
import _ from './utils';
|
||||||
|
|
||||||
|
const Footer = (props) => {
|
||||||
|
const { data, className, columns } = props;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<tfoot>
|
||||||
|
<tr className={ className }>
|
||||||
|
{columns.map((column, i) => {
|
||||||
|
if (column.footer === undefined || column.footer === null || column.hidden) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const columnData = _.pluck(data, column.dataField);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<FooterCell
|
||||||
|
index={ i }
|
||||||
|
key={ column.dataField }
|
||||||
|
column={ column }
|
||||||
|
columnData={ columnData }
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</tr>
|
||||||
|
</tfoot>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
Footer.propTypes = {
|
||||||
|
data: PropTypes.array,
|
||||||
|
className: PropTypes.string,
|
||||||
|
columns: PropTypes.array
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Footer;
|
||||||
61
packages/react-bootstrap-table2/test/footer.test.js
Normal file
61
packages/react-bootstrap-table2/test/footer.test.js
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
/* eslint no-unused-vars: 0 */
|
||||||
|
import 'jsdom-global/register';
|
||||||
|
import React from 'react';
|
||||||
|
import { shallow, mount } from 'enzyme';
|
||||||
|
|
||||||
|
import Footer from '../src/footer';
|
||||||
|
import FooterCell from '../src/footer-cell';
|
||||||
|
|
||||||
|
describe('Footer', () => {
|
||||||
|
let wrapper;
|
||||||
|
const columns = [
|
||||||
|
{
|
||||||
|
dataField: 'id',
|
||||||
|
text: 'ID',
|
||||||
|
footer: 'Footer 1'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
dataField: 'name',
|
||||||
|
text: 'Name',
|
||||||
|
footer: (columnData, column) => 'Footer 2'
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
const data = [
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
name: 'A'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
name: 'B'
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
const keyField = 'id';
|
||||||
|
|
||||||
|
describe('simplest header', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
wrapper = shallow(<Footer data={ data } columns={ columns } />);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should render successfully', () => {
|
||||||
|
expect(wrapper.length).toBe(1);
|
||||||
|
expect(wrapper.find('tr').length).toBe(1);
|
||||||
|
expect(wrapper.find(FooterCell).length).toBe(columns.length);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('className prop is exists', () => {
|
||||||
|
const className = 'test-class';
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
wrapper = shallow(<Footer data={ data } columns={ columns } className={ className } />);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should render successfully', () => {
|
||||||
|
expect(wrapper.length).toBe(1);
|
||||||
|
expect(wrapper.find(`.${className}`).length).toBe(1);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
Loading…
Reference in New Issue
Block a user