mirror of
https://github.com/gosticks/react-bootstrap-table2.git
synced 2025-10-16 11:55:39 +00:00
fix pagination broken when bootstrap4
This commit is contained in:
parent
495875792f
commit
3f957db56b
6
packages/react-bootstrap-table2-paginator/src/bootstrap.js
vendored
Normal file
6
packages/react-bootstrap-table2-paginator/src/bootstrap.js
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
import React from 'react';
|
||||
|
||||
// consider to have a common lib?1
|
||||
export const BootstrapContext = React.createContext({
|
||||
bootstrap4: false
|
||||
});
|
||||
@ -5,6 +5,7 @@ import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import Const from './const';
|
||||
import { BootstrapContext } from './bootstrap';
|
||||
import Pagination from './pagination';
|
||||
import { getByCurrPage, alignPage } from './page';
|
||||
|
||||
@ -123,7 +124,7 @@ export default (
|
||||
|
||||
render() {
|
||||
let { data } = this.props;
|
||||
const { pagination: { options } } = this.props;
|
||||
const { pagination: { options }, bootstrap4 } = this.props;
|
||||
const { currPage, currSizePerPage } = this;
|
||||
const withFirstAndLast = typeof options.withFirstAndLast === 'undefined' ?
|
||||
Const.With_FIRST_AND_LAST : options.withFirstAndLast;
|
||||
@ -148,31 +149,33 @@ export default (
|
||||
return (
|
||||
<PaginationContext.Provider value={ { data } }>
|
||||
{ this.props.children }
|
||||
<Pagination
|
||||
key="pagination"
|
||||
dataSize={ options.totalSize || this.props.data.length }
|
||||
currPage={ currPage }
|
||||
currSizePerPage={ currSizePerPage }
|
||||
onPageChange={ this.handleChangePage }
|
||||
onSizePerPageChange={ this.handleChangeSizePerPage }
|
||||
sizePerPageList={ options.sizePerPageList || Const.SIZE_PER_PAGE_LIST }
|
||||
paginationSize={ options.paginationSize || Const.PAGINATION_SIZE }
|
||||
pageStartIndex={ pageStartIndex }
|
||||
withFirstAndLast={ withFirstAndLast }
|
||||
alwaysShowAllBtns={ alwaysShowAllBtns }
|
||||
hideSizePerPage={ hideSizePerPage }
|
||||
hidePageListOnlyOnePage={ hidePageListOnlyOnePage }
|
||||
showTotal={ options.showTotal }
|
||||
paginationTotalRenderer={ options.paginationTotalRenderer }
|
||||
firstPageText={ options.firstPageText || Const.FIRST_PAGE_TEXT }
|
||||
prePageText={ options.prePageText || Const.PRE_PAGE_TEXT }
|
||||
nextPageText={ options.nextPageText || Const.NEXT_PAGE_TEXT }
|
||||
lastPageText={ options.lastPageText || Const.LAST_PAGE_TEXT }
|
||||
prePageTitle={ options.prePageTitle || Const.PRE_PAGE_TITLE }
|
||||
nextPageTitle={ options.nextPageTitle || Const.NEXT_PAGE_TITLE }
|
||||
firstPageTitle={ options.firstPageTitle || Const.FIRST_PAGE_TITLE }
|
||||
lastPageTitle={ options.lastPageTitle || Const.LAST_PAGE_TITLE }
|
||||
/>
|
||||
<BootstrapContext.Provider value={ { bootstrap4 } }>
|
||||
<Pagination
|
||||
key="pagination"
|
||||
dataSize={ options.totalSize || this.props.data.length }
|
||||
currPage={ currPage }
|
||||
currSizePerPage={ currSizePerPage }
|
||||
onPageChange={ this.handleChangePage }
|
||||
onSizePerPageChange={ this.handleChangeSizePerPage }
|
||||
sizePerPageList={ options.sizePerPageList || Const.SIZE_PER_PAGE_LIST }
|
||||
paginationSize={ options.paginationSize || Const.PAGINATION_SIZE }
|
||||
pageStartIndex={ pageStartIndex }
|
||||
withFirstAndLast={ withFirstAndLast }
|
||||
alwaysShowAllBtns={ alwaysShowAllBtns }
|
||||
hideSizePerPage={ hideSizePerPage }
|
||||
hidePageListOnlyOnePage={ hidePageListOnlyOnePage }
|
||||
showTotal={ options.showTotal }
|
||||
paginationTotalRenderer={ options.paginationTotalRenderer }
|
||||
firstPageText={ options.firstPageText || Const.FIRST_PAGE_TEXT }
|
||||
prePageText={ options.prePageText || Const.PRE_PAGE_TEXT }
|
||||
nextPageText={ options.nextPageText || Const.NEXT_PAGE_TEXT }
|
||||
lastPageText={ options.lastPageText || Const.LAST_PAGE_TEXT }
|
||||
prePageTitle={ options.prePageTitle || Const.PRE_PAGE_TITLE }
|
||||
nextPageTitle={ options.nextPageTitle || Const.NEXT_PAGE_TITLE }
|
||||
firstPageTitle={ options.firstPageTitle || Const.FIRST_PAGE_TITLE }
|
||||
lastPageTitle={ options.lastPageTitle || Const.LAST_PAGE_TITLE }
|
||||
/>
|
||||
</BootstrapContext.Provider>
|
||||
</PaginationContext.Provider>
|
||||
);
|
||||
}
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import React from 'react';
|
||||
import cs from 'classnames';
|
||||
import PropTypes from 'prop-types';
|
||||
import { BootstrapContext } from './bootstrap';
|
||||
import SizePerPageOption from './size-per-page-option';
|
||||
|
||||
const sizePerPageDefaultClass = 'react-bs-table-sizePerPage-dropdown';
|
||||
@ -20,44 +21,60 @@ const SizePerPageDropDown = (props) => {
|
||||
} = props;
|
||||
|
||||
const dropDownStyle = { visibility: hidden ? 'hidden' : 'visible' };
|
||||
const openClass = open ? 'open show' : '';
|
||||
const dropdownClasses = cs(
|
||||
open ? 'open show' : '',
|
||||
openClass,
|
||||
sizePerPageDefaultClass,
|
||||
variation,
|
||||
className,
|
||||
);
|
||||
|
||||
return (
|
||||
<span
|
||||
style={ dropDownStyle }
|
||||
className={ dropdownClasses }
|
||||
>
|
||||
<button
|
||||
id="pageDropDown"
|
||||
className={ `btn ${btnContextual} dropdown-toggle` }
|
||||
data-toggle="dropdown"
|
||||
aria-expanded={ open }
|
||||
onClick={ onClick }
|
||||
onBlur={ onBlur }
|
||||
>
|
||||
{ currSizePerPage }
|
||||
<span>
|
||||
{ ' ' }
|
||||
<span className="caret" />
|
||||
</span>
|
||||
</button>
|
||||
<ul className="dropdown-menu" role="menu" aria-labelledby="pageDropDown">
|
||||
{
|
||||
options.map(option => (
|
||||
<SizePerPageOption
|
||||
{ ...option }
|
||||
key={ option.text }
|
||||
onSizePerPageChange={ onSizePerPageChange }
|
||||
/>
|
||||
))
|
||||
}
|
||||
</ul>
|
||||
</span>
|
||||
<BootstrapContext.Consumer>
|
||||
{
|
||||
({ bootstrap4 }) => (
|
||||
<span
|
||||
style={ dropDownStyle }
|
||||
className={ dropdownClasses }
|
||||
>
|
||||
<button
|
||||
id="pageDropDown"
|
||||
className={ `btn ${btnContextual} dropdown-toggle` }
|
||||
data-toggle="dropdown"
|
||||
aria-expanded={ open }
|
||||
onClick={ onClick }
|
||||
onBlur={ onBlur }
|
||||
>
|
||||
{ currSizePerPage }
|
||||
{ ' ' }
|
||||
{
|
||||
bootstrap4 ? null : (
|
||||
<span>
|
||||
<span className="caret" />
|
||||
</span>
|
||||
)
|
||||
}
|
||||
</button>
|
||||
<ul
|
||||
className={ `dropdown-menu ${openClass}` }
|
||||
role="menu"
|
||||
aria-labelledby="pageDropDown"
|
||||
>
|
||||
{
|
||||
options.map(option => (
|
||||
<SizePerPageOption
|
||||
{ ...option }
|
||||
key={ option.text }
|
||||
bootstrap4={ bootstrap4 }
|
||||
onSizePerPageChange={ onSizePerPageChange }
|
||||
/>
|
||||
))
|
||||
}
|
||||
</ul>
|
||||
</span>
|
||||
)
|
||||
}
|
||||
</BootstrapContext.Consumer>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@ -5,9 +5,28 @@ import PropTypes from 'prop-types';
|
||||
const SizePerPageOption = ({
|
||||
text,
|
||||
page,
|
||||
onSizePerPageChange
|
||||
}) => (
|
||||
<li key={ text } role="presentation" className="dropdown-item">
|
||||
onSizePerPageChange,
|
||||
bootstrap4
|
||||
}) => (bootstrap4 ? (
|
||||
<a
|
||||
href="#"
|
||||
tabIndex="-1"
|
||||
role="menuitem"
|
||||
className="dropdown-item"
|
||||
data-page={ page }
|
||||
onMouseDown={ (e) => {
|
||||
e.preventDefault();
|
||||
onSizePerPageChange(page);
|
||||
} }
|
||||
>
|
||||
{ text }
|
||||
</a>
|
||||
) : (
|
||||
<li
|
||||
key={ text }
|
||||
role="presentation"
|
||||
className="dropdown-item"
|
||||
>
|
||||
<a
|
||||
href="#"
|
||||
tabIndex="-1"
|
||||
@ -21,12 +40,17 @@ const SizePerPageOption = ({
|
||||
{ text }
|
||||
</a>
|
||||
</li>
|
||||
);
|
||||
));
|
||||
|
||||
SizePerPageOption.propTypes = {
|
||||
text: PropTypes.string.isRequired,
|
||||
page: PropTypes.number.isRequired,
|
||||
onSizePerPageChange: PropTypes.func.isRequired
|
||||
onSizePerPageChange: PropTypes.func.isRequired,
|
||||
bootstrap4: PropTypes.bool
|
||||
};
|
||||
|
||||
SizePerPageOption.defaultProps = {
|
||||
bootstrap4: false
|
||||
};
|
||||
|
||||
export default SizePerPageOption;
|
||||
|
||||
@ -5,6 +5,12 @@ import { shallow } from 'enzyme';
|
||||
import SizePerPageOption from '../src/size-per-page-option';
|
||||
import SizePerPageDropDown from '../src/size-per-page-dropdown';
|
||||
|
||||
const shallowWithContext = (elem, context = {}) => {
|
||||
const wrapper = shallow(elem);
|
||||
const Children = wrapper.props().children(context);
|
||||
return shallow(Children);
|
||||
};
|
||||
|
||||
describe('SizePerPageDropDown', () => {
|
||||
let wrapper;
|
||||
const currSizePerPage = '25';
|
||||
@ -28,8 +34,9 @@ describe('SizePerPageDropDown', () => {
|
||||
|
||||
describe('default SizePerPageDropDown component', () => {
|
||||
beforeEach(() => {
|
||||
wrapper = shallow(
|
||||
<SizePerPageDropDown { ...props } />
|
||||
wrapper = shallowWithContext(
|
||||
<SizePerPageDropDown { ...props } />,
|
||||
{ bootstrap4: false }
|
||||
);
|
||||
});
|
||||
|
||||
@ -47,6 +54,7 @@ describe('SizePerPageDropDown', () => {
|
||||
const option = options[i];
|
||||
expect(sizePerPage.prop('text')).toEqual(option.text);
|
||||
expect(sizePerPage.prop('page')).toEqual(option.page);
|
||||
expect(sizePerPage.prop('bootstrap4')).toBeFalsy();
|
||||
expect(sizePerPage.prop('onSizePerPageChange')).toEqual(onSizePerPageChange);
|
||||
});
|
||||
});
|
||||
@ -61,10 +69,52 @@ describe('SizePerPageDropDown', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('when bootstrap4 context is true', () => {
|
||||
beforeEach(() => {
|
||||
wrapper = shallowWithContext(
|
||||
<SizePerPageDropDown { ...props } />,
|
||||
{ bootstrap4: true }
|
||||
);
|
||||
});
|
||||
|
||||
it('should rendering SizePerPageDropDown correctly', () => {
|
||||
expect(wrapper.length).toBe(1);
|
||||
expect(wrapper.find('button').length).toBe(1);
|
||||
expect(wrapper.find('button').text()).toEqual(`${currSizePerPage} `);
|
||||
});
|
||||
|
||||
it('should rendering SizePerPageOption successfully', () => {
|
||||
expect(wrapper.find('ul.dropdown-menu').length).toBe(1);
|
||||
const sizePerPageOptions = wrapper.find(SizePerPageOption);
|
||||
expect(sizePerPageOptions.length).toBe(options.length);
|
||||
sizePerPageOptions.forEach((sizePerPage, i) => {
|
||||
const option = options[i];
|
||||
expect(sizePerPage.prop('text')).toEqual(option.text);
|
||||
expect(sizePerPage.prop('page')).toEqual(option.page);
|
||||
expect(sizePerPage.prop('bootstrap4')).toBeTruthy();
|
||||
expect(sizePerPage.prop('onSizePerPageChange')).toEqual(onSizePerPageChange);
|
||||
});
|
||||
});
|
||||
|
||||
it('no need to render caret', () => {
|
||||
expect(wrapper.find('.caret')).toHaveLength(0);
|
||||
});
|
||||
|
||||
it('default variation is dropdown', () => {
|
||||
expect(wrapper.hasClass('dropdown')).toBeTruthy();
|
||||
});
|
||||
|
||||
it('default dropdown is not open', () => {
|
||||
expect(wrapper.hasClass('open show')).toBeFalsy();
|
||||
expect(wrapper.find('[aria-expanded=false]').length).toBe(1);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when open prop is true', () => {
|
||||
beforeEach(() => {
|
||||
wrapper = shallow(
|
||||
<SizePerPageDropDown { ...props } open />
|
||||
wrapper = shallowWithContext(
|
||||
<SizePerPageDropDown { ...props } open />,
|
||||
{ bootstrap4: false }
|
||||
);
|
||||
});
|
||||
|
||||
@ -76,8 +126,9 @@ describe('SizePerPageDropDown', () => {
|
||||
|
||||
describe('when hidden prop is true', () => {
|
||||
beforeEach(() => {
|
||||
wrapper = shallow(
|
||||
<SizePerPageDropDown { ...props } hidden />
|
||||
wrapper = shallowWithContext(
|
||||
<SizePerPageDropDown { ...props } hidden />,
|
||||
{ bootstrap4: false }
|
||||
);
|
||||
});
|
||||
|
||||
@ -89,8 +140,9 @@ describe('SizePerPageDropDown', () => {
|
||||
describe('when btnContextual prop is defined', () => {
|
||||
const contextual = 'btn-warning';
|
||||
beforeEach(() => {
|
||||
wrapper = shallow(
|
||||
<SizePerPageDropDown { ...props } btnContextual={ contextual } />
|
||||
wrapper = shallowWithContext(
|
||||
<SizePerPageDropDown { ...props } btnContextual={ contextual } />,
|
||||
{ bootstrap4: false }
|
||||
);
|
||||
});
|
||||
|
||||
@ -102,8 +154,9 @@ describe('SizePerPageDropDown', () => {
|
||||
describe('when variation prop is defined', () => {
|
||||
const variation = 'dropup';
|
||||
beforeEach(() => {
|
||||
wrapper = shallow(
|
||||
<SizePerPageDropDown { ...props } variation={ variation } />
|
||||
wrapper = shallowWithContext(
|
||||
<SizePerPageDropDown { ...props } variation={ variation } />,
|
||||
{ bootstrap4: false }
|
||||
);
|
||||
});
|
||||
|
||||
@ -115,8 +168,9 @@ describe('SizePerPageDropDown', () => {
|
||||
describe('when className prop is defined', () => {
|
||||
const className = 'custom-class';
|
||||
beforeEach(() => {
|
||||
wrapper = shallow(
|
||||
<SizePerPageDropDown { ...props } className={ className } />
|
||||
wrapper = shallowWithContext(
|
||||
<SizePerPageDropDown { ...props } className={ className } />,
|
||||
{ bootstrap4: false }
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
@ -11,29 +11,64 @@ describe('SizePerPageOption', () => {
|
||||
const onSizePerPageChange = sinon.stub();
|
||||
|
||||
beforeEach(() => {
|
||||
const props = { text, page, onSizePerPageChange };
|
||||
wrapper = shallow(
|
||||
<SizePerPageOption { ...props } />
|
||||
);
|
||||
onSizePerPageChange.reset();
|
||||
});
|
||||
|
||||
it('should render SizePerPageOption correctly', () => {
|
||||
expect(wrapper.length).toBe(1);
|
||||
expect(wrapper.find('.dropdown-item').length).toBe(1);
|
||||
expect(wrapper.find(`[data-page=${page}]`).length).toBe(1);
|
||||
expect(wrapper.text()).toEqual(text);
|
||||
});
|
||||
|
||||
describe('when MouseDown event happen', () => {
|
||||
const preventDefault = sinon.stub();
|
||||
describe('when bootstrap4 prop is true', () => {
|
||||
beforeEach(() => {
|
||||
wrapper.find('a').simulate('mousedown', { preventDefault });
|
||||
const props = { text, page, onSizePerPageChange };
|
||||
wrapper = shallow(
|
||||
<SizePerPageOption { ...props } />
|
||||
);
|
||||
});
|
||||
|
||||
it('should calling props.onSizePerPageChange correctly', () => {
|
||||
expect(preventDefault.calledOnce).toBeTruthy();
|
||||
expect(onSizePerPageChange.calledOnce).toBeTruthy();
|
||||
expect(onSizePerPageChange.calledWith(page)).toBeTruthy();
|
||||
it('should render SizePerPageOption correctly', () => {
|
||||
expect(wrapper.length).toBe(1);
|
||||
expect(wrapper.find('li.dropdown-item').length).toBe(1);
|
||||
expect(wrapper.find(`[data-page=${page}]`).length).toBe(1);
|
||||
expect(wrapper.text()).toEqual(text);
|
||||
});
|
||||
|
||||
describe('when MouseDown event happen', () => {
|
||||
const preventDefault = sinon.stub();
|
||||
beforeEach(() => {
|
||||
wrapper.find('a').simulate('mousedown', { preventDefault });
|
||||
});
|
||||
|
||||
it('should calling props.onSizePerPageChange correctly', () => {
|
||||
expect(preventDefault.calledOnce).toBeTruthy();
|
||||
expect(onSizePerPageChange.calledOnce).toBeTruthy();
|
||||
expect(onSizePerPageChange.calledWith(page)).toBeTruthy();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('when bootstrap4 prop is true', () => {
|
||||
beforeEach(() => {
|
||||
const props = { text, page, onSizePerPageChange };
|
||||
wrapper = shallow(
|
||||
<SizePerPageOption { ...props } bootstrap4 />
|
||||
);
|
||||
});
|
||||
|
||||
it('should render SizePerPageOption correctly', () => {
|
||||
expect(wrapper.length).toBe(1);
|
||||
expect(wrapper.find('a.dropdown-item').length).toBe(1);
|
||||
expect(wrapper.find(`[data-page=${page}]`).length).toBe(1);
|
||||
expect(wrapper.text()).toEqual(text);
|
||||
});
|
||||
|
||||
describe('when MouseDown event happen', () => {
|
||||
const preventDefault = sinon.stub();
|
||||
beforeEach(() => {
|
||||
wrapper.find('a').simulate('mousedown', { preventDefault });
|
||||
});
|
||||
|
||||
it('should calling props.onSizePerPageChange correctly', () => {
|
||||
expect(preventDefault.calledOnce).toBeTruthy();
|
||||
expect(onSizePerPageChange.calledOnce).toBeTruthy();
|
||||
expect(onSizePerPageChange.calledWith(page)).toBeTruthy();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@ -155,6 +155,7 @@ const withContext = Base =>
|
||||
ref={ n => this.paginationContext = n }
|
||||
pagination={ this.props.pagination }
|
||||
data={ rootProps.getData(filterProps, searchProps, sortProps) }
|
||||
bootstrap4={ this.props.bootstrap4 }
|
||||
>
|
||||
<this.PaginationContext.Consumer>
|
||||
{
|
||||
|
||||
Loading…
Reference in New Issue
Block a user