diff --git a/packages/react-bootstrap-table2-filter/src/context.js b/packages/react-bootstrap-table2-filter/src/context.js index e82e53e..8d375ca 100644 --- a/packages/react-bootstrap-table2-filter/src/context.js +++ b/packages/react-bootstrap-table2-filter/src/context.js @@ -17,7 +17,8 @@ export default ( class FilterProvider extends React.Component { static propTypes = { data: PropTypes.array.isRequired, - columns: PropTypes.array.isRequired + columns: PropTypes.array.isRequired, + listenerForPagination: PropTypes.object } constructor(props) { @@ -25,6 +26,9 @@ export default ( this.currFilters = {}; this.onFilter = this.onFilter.bind(this); this.onExternalFilter = this.onExternalFilter.bind(this); + this.state = { + data: props.data + }; } componentDidMount() { @@ -68,7 +72,12 @@ export default ( filter.props.onFilter(filterVal); } - this.forceUpdate(); + const { listenerForPagination, data } = this.props; + const result = filters(data, this.props.columns, _)(this.currFilters); + if (listenerForPagination) { + listenerForPagination.emit('filterChanged', result.length); + } + this.setState({ data: result }); }; } @@ -79,13 +88,9 @@ export default ( } render() { - let { data } = this.props; - if (!isRemoteFiltering()) { - data = filters(data, this.props.columns, _)(this.currFilters); - } return ( { function shallowContext( enableRemote = false, - tableColumns = columns + tableColumns = columns, + listenerForPagination, ) { mockBase.mockReset(); handleFilterChange.mockReset(); @@ -59,6 +60,7 @@ describe('FilterContext', () => { { @@ -252,6 +254,23 @@ describe('FilterContext', () => { }); }); + describe('when props.listenerForPagination is defined', () => { + const filterVal = '3'; + const newDataLength = 0; + const listenerForPagination = { emit: jest.fn() }; + + beforeEach(() => { + wrapper = shallow(shallowContext(false, columns, listenerForPagination)); + wrapper.render(); + instance = wrapper.instance(); + }); + + it('should call listenerForPagination.emit correctly', () => { + instance.onFilter(columns[1], FILTER_TYPE.TEXT)(filterVal); + expect(listenerForPagination.emit).toHaveBeenCalledWith('filterChanged', newDataLength); + }); + }); + describe('combination', () => { beforeEach(() => { wrapper = shallow(shallowContext()); diff --git a/packages/react-bootstrap-table2-paginator/src/state-context.js b/packages/react-bootstrap-table2-paginator/src/state-context.js index 758dd95..ae5f26a 100644 --- a/packages/react-bootstrap-table2-paginator/src/state-context.js +++ b/packages/react-bootstrap-table2-paginator/src/state-context.js @@ -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.filterListener = new EventEmitter(); + this.filterListener.on('filterChanged', this.handleDataSizeChange); } componentWillReceiveProps(nextProps) { @@ -51,7 +57,7 @@ class StateProvider extends React.Component { 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 +78,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 +112,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 +173,8 @@ class StateProvider extends React.Component { paginationProps, paginationTableProps: { pagination, - setPaginationRemoteEmitter: this.setPaginationRemoteEmitter + setPaginationRemoteEmitter: this.setPaginationRemoteEmitter, + listenerForPagination: this.filterListener } } } > diff --git a/packages/react-bootstrap-table2-paginator/test/state-context.test.js b/packages/react-bootstrap-table2-paginator/test/state-context.test.js index 828c667..956b4ba 100644 --- a/packages/react-bootstrap-table2-paginator/test/state-context.test.js +++ b/packages/react-bootstrap-table2-paginator/test/state-context.test.js @@ -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, + listenerForPagination: instance.filterListener } }); }); @@ -182,6 +187,31 @@ describe('PaginationStateContext', () => { }); }); + 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 +373,8 @@ describe('PaginationStateContext', () => { createContext: expect.any(Function), options: instance.getPaginationProps() }, - setPaginationRemoteEmitter: instance.setPaginationRemoteEmitter + setPaginationRemoteEmitter: instance.setPaginationRemoteEmitter, + listenerForPagination: instance.filterListener } }); }); @@ -374,7 +405,8 @@ describe('PaginationStateContext', () => { createContext: expect.any(Function), options: instance.getPaginationProps() }, - setPaginationRemoteEmitter: instance.setPaginationRemoteEmitter + setPaginationRemoteEmitter: instance.setPaginationRemoteEmitter, + listenerForPagination: instance.filterListener } }); }); @@ -401,7 +433,8 @@ describe('PaginationStateContext', () => { createContext: expect.any(Function), options: instance.getPaginationProps() }, - setPaginationRemoteEmitter: instance.setPaginationRemoteEmitter + setPaginationRemoteEmitter: instance.setPaginationRemoteEmitter, + listenerForPagination: instance.filterListener } }); }); @@ -428,7 +461,8 @@ describe('PaginationStateContext', () => { createContext: expect.any(Function), options: instance.getPaginationProps() }, - setPaginationRemoteEmitter: instance.setPaginationRemoteEmitter + setPaginationRemoteEmitter: instance.setPaginationRemoteEmitter, + listenerForPagination: instance.filterListener } }); }); @@ -455,7 +489,8 @@ describe('PaginationStateContext', () => { createContext: expect.any(Function), options: instance.getPaginationProps() }, - setPaginationRemoteEmitter: instance.setPaginationRemoteEmitter + setPaginationRemoteEmitter: instance.setPaginationRemoteEmitter, + listenerForPagination: instance.filterListener } }); }); @@ -482,7 +517,8 @@ describe('PaginationStateContext', () => { createContext: expect.any(Function), options: instance.getPaginationProps() }, - setPaginationRemoteEmitter: instance.setPaginationRemoteEmitter + setPaginationRemoteEmitter: instance.setPaginationRemoteEmitter, + listenerForPagination: instance.filterListener } }); }); @@ -509,7 +545,8 @@ describe('PaginationStateContext', () => { createContext: expect.any(Function), options: instance.getPaginationProps() }, - setPaginationRemoteEmitter: instance.setPaginationRemoteEmitter + setPaginationRemoteEmitter: instance.setPaginationRemoteEmitter, + listenerForPagination: instance.filterListener } }); }); @@ -536,7 +573,8 @@ describe('PaginationStateContext', () => { createContext: expect.any(Function), options: instance.getPaginationProps() }, - setPaginationRemoteEmitter: instance.setPaginationRemoteEmitter + setPaginationRemoteEmitter: instance.setPaginationRemoteEmitter, + listenerForPagination: instance.filterListener } }); }); @@ -563,7 +601,8 @@ describe('PaginationStateContext', () => { createContext: expect.any(Function), options: instance.getPaginationProps() }, - setPaginationRemoteEmitter: instance.setPaginationRemoteEmitter + setPaginationRemoteEmitter: instance.setPaginationRemoteEmitter, + listenerForPagination: instance.filterListener } }); }); @@ -590,7 +629,8 @@ describe('PaginationStateContext', () => { createContext: expect.any(Function), options: instance.getPaginationProps() }, - setPaginationRemoteEmitter: instance.setPaginationRemoteEmitter + setPaginationRemoteEmitter: instance.setPaginationRemoteEmitter, + listenerForPagination: instance.filterListener } }); }); @@ -617,7 +657,8 @@ describe('PaginationStateContext', () => { createContext: expect.any(Function), options: instance.getPaginationProps() }, - setPaginationRemoteEmitter: instance.setPaginationRemoteEmitter + setPaginationRemoteEmitter: instance.setPaginationRemoteEmitter, + listenerForPagination: instance.filterListener } }); }); @@ -644,7 +685,8 @@ describe('PaginationStateContext', () => { createContext: expect.any(Function), options: instance.getPaginationProps() }, - setPaginationRemoteEmitter: instance.setPaginationRemoteEmitter + setPaginationRemoteEmitter: instance.setPaginationRemoteEmitter, + listenerForPagination: instance.filterListener } }); }); @@ -671,7 +713,8 @@ describe('PaginationStateContext', () => { createContext: expect.any(Function), options: instance.getPaginationProps() }, - setPaginationRemoteEmitter: instance.setPaginationRemoteEmitter + setPaginationRemoteEmitter: instance.setPaginationRemoteEmitter, + listenerForPagination: instance.filterListener } }); }); @@ -698,7 +741,8 @@ describe('PaginationStateContext', () => { createContext: expect.any(Function), options: instance.getPaginationProps() }, - setPaginationRemoteEmitter: instance.setPaginationRemoteEmitter + setPaginationRemoteEmitter: instance.setPaginationRemoteEmitter, + listenerForPagination: instance.filterListener } }); }); @@ -725,7 +769,8 @@ describe('PaginationStateContext', () => { createContext: expect.any(Function), options: instance.getPaginationProps() }, - setPaginationRemoteEmitter: instance.setPaginationRemoteEmitter + setPaginationRemoteEmitter: instance.setPaginationRemoteEmitter, + listenerForPagination: instance.filterListener } }); }); @@ -752,7 +797,8 @@ describe('PaginationStateContext', () => { createContext: expect.any(Function), options: instance.getPaginationProps() }, - setPaginationRemoteEmitter: instance.setPaginationRemoteEmitter + setPaginationRemoteEmitter: instance.setPaginationRemoteEmitter, + listenerForPagination: instance.filterListener } }); }); @@ -779,7 +825,8 @@ describe('PaginationStateContext', () => { createContext: expect.any(Function), options: instance.getPaginationProps() }, - setPaginationRemoteEmitter: instance.setPaginationRemoteEmitter + setPaginationRemoteEmitter: instance.setPaginationRemoteEmitter, + listenerForPagination: instance.filterListener } }); }); @@ -806,7 +853,8 @@ describe('PaginationStateContext', () => { createContext: expect.any(Function), options: instance.getPaginationProps() }, - setPaginationRemoteEmitter: instance.setPaginationRemoteEmitter + setPaginationRemoteEmitter: instance.setPaginationRemoteEmitter, + listenerForPagination: instance.filterListener } }); }); @@ -833,7 +881,8 @@ describe('PaginationStateContext', () => { createContext: expect.any(Function), options: instance.getPaginationProps() }, - setPaginationRemoteEmitter: instance.setPaginationRemoteEmitter + setPaginationRemoteEmitter: instance.setPaginationRemoteEmitter, + listenerForPagination: instance.filterListener } }); }); diff --git a/packages/react-bootstrap-table2/src/contexts/index.js b/packages/react-bootstrap-table2/src/contexts/index.js index 7caf60c..6a32589 100644 --- a/packages/react-bootstrap-table2/src/contexts/index.js +++ b/packages/react-bootstrap-table2/src/contexts/index.js @@ -237,6 +237,7 @@ const withContext = Base => { ...baseProps } ref={ n => this.filterContext = n } data={ rootProps.getData() } + listenerForPagination={ this.props.listenerForPagination } > {