Skip to content
This repository was archived by the owner on Jun 4, 2024. It is now read-only.

Commit 0ed2bea

Browse files
author
Shammamah Hossain
authored
Merge pull request #595 from plotly/page-numbers-pagination
Page numbers and page navigation improvements
2 parents f3737af + cccf613 commit 0ed2bea

File tree

13 files changed

+952
-424
lines changed

13 files changed

+952
-424
lines changed

CHANGELOG.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,22 @@ This project adheres to [Semantic Versioning](http://semver.org/).
1010
[#597](https://github.com/plotly/dash-table/issues/597)
1111
- Add `is blank` unary operator. Returns true for `undefined`, `null` and `''`.
1212

13+
[#299](https://github.com/plotly/dash-table/issues/299)
14+
- New prop `page_count` that sets the maximum number of pages that are
15+
accessible via the pagination menu when using backend pagination.
16+
1317
### Changed
1418
[#598](https://github.com/plotly/dash-table/issues/598)
1519
- Allow values with whitespaces in column filters
1620

21+
[#580](https://github.com/plotly/dash-table/issues/580)
22+
- Change pagination menu button UI to use arrow icons instead of plain
23+
buttons
24+
- Move pagination menu to bottom-right of table
25+
- Include go-to-first and go-to-last buttons
26+
- Include current-page and total-pages display in pagination menu
27+
- Include input box for user to navigate directly to a page
28+
1729
### Fixed
1830
[#460](https://github.com/plotly/dash-table/issues/460)
1931
- The `datestartswith` relational operator now supports number comparison

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
"private::host_dash8083": "python tests/cypress/dash/v_fe_page.py",
2828
"private::host_dash8084": "python tests/cypress/dash/v_data_loading.py",
2929
"private::host_dash8085": "python tests/cypress/dash/v_default.py",
30+
"private::host_dash8086": "python tests/cypress/dash/v_pagination.py",
3031
"private::host_js": "http-server ./dash_table -c-1 --silent",
3132
"private::lint:ts": "tslint --project tsconfig.json --config tslint.json",
3233
"private::lint:py": "flake8 --exclude=DataTable.py,__init__.py,_imports_.py dash_table",
@@ -35,6 +36,7 @@
3536
"private::wait_dash8083": "wait-on http://localhost:8083",
3637
"private::wait_dash8084": "wait-on http://localhost:8084",
3738
"private::wait_dash8085": "wait-on http://localhost:8085",
39+
"private::wait_dash8086": "wait-on http://localhost:8086",
3840
"private::wait_js": "wait-on http://localhost:8080",
3941
"private::opentests": "cypress open",
4042
"private::test.python": "python -m unittest tests/unit/format_test.py",

src/dash-table/components/ControlledTable/index.tsx

Lines changed: 8 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@ import queryLexicon from 'dash-table/syntax-tree/lexicon/query';
3838
import dataLoading from 'dash-table/derived/table/data_loading';
3939
import reconcile from 'dash-table/type/reconcile';
4040

41+
import PageNavigation from 'dash-table/components/PageNavigation';
42+
4143
const DEFAULT_STYLE = {
4244
width: '100%'
4345
};
@@ -629,18 +631,6 @@ export default class ControlledTable extends PureComponent<ControlledTableProps>
629631
) || page_action === TableAction.Custom;
630632
}
631633

632-
loadNext = () => {
633-
const { paginator } = this.props;
634-
635-
paginator.loadNext();
636-
}
637-
638-
loadPrevious = () => {
639-
const { paginator } = this.props;
640-
641-
paginator.loadPrevious();
642-
}
643-
644634
applyStyle = () => {
645635
const {
646636
fixed_columns,
@@ -807,7 +797,7 @@ export default class ControlledTable extends PureComponent<ControlledTableProps>
807797
tooltip_duration
808798
);
809799

810-
const { export_columns, export_format, export_headers, virtual, merge_duplicate_headers } = this.props;
800+
const { export_columns, export_format, export_headers, virtual, merge_duplicate_headers, paginator, page_current, page_count } = this.props;
811801
const buttonProps = {
812802
export_columns,
813803
export_format,
@@ -820,6 +810,7 @@ export default class ControlledTable extends PureComponent<ControlledTableProps>
820810

821811
return (<div
822812
id={id}
813+
className='dash-table-container'
823814
onCopy={this.onCopy}
824815
onKeyDown={this.handleKeyDown}
825816
onPaste={this.onPaste}
@@ -859,10 +850,10 @@ export default class ControlledTable extends PureComponent<ControlledTableProps>
859850
</div>
860851
</div>
861852
{!this.displayPagination ? null : (
862-
<div>
863-
<button className='previous-page' onClick={this.loadPrevious}>Previous</button>
864-
<button className='next-page' onClick={this.loadNext}>Next</button>
865-
</div>
853+
<PageNavigation
854+
paginator={paginator}
855+
page_current={page_current}
856+
page_count={page_count} />
866857
)}
867858
</div>);
868859
}
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
import React, { Component } from 'react';
2+
import { IPageNavigationProps } from 'dash-table/components/PageNavigation/props';
3+
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
4+
import { KEY_CODES } from 'dash-table/utils/unicode';
5+
6+
export default class PageNavigation extends Component<IPageNavigationProps> {
7+
8+
constructor(props: IPageNavigationProps) {
9+
super(props);
10+
}
11+
12+
goToPage = (page_number: string) => {
13+
const { paginator } = this.props;
14+
15+
let page = parseInt(page_number, 10);
16+
17+
if (isNaN(page)) {
18+
return;
19+
}
20+
21+
paginator.loadPage(page - 1);
22+
}
23+
24+
render() {
25+
const {
26+
paginator,
27+
page_current
28+
} = this.props;
29+
30+
return (paginator.lastPage !== undefined && paginator.lastPage <= 0) ? null : (
31+
<div className='previous-next-container'>
32+
<button
33+
className='first-page'
34+
onClick={paginator.loadFirst}
35+
disabled={!paginator.hasPrevious()}>
36+
<FontAwesomeIcon icon='angle-double-left' />
37+
</button>
38+
39+
<button
40+
className='previous-page'
41+
onClick={paginator.loadPrevious}
42+
disabled={!paginator.hasPrevious()}>
43+
<FontAwesomeIcon icon='angle-left' />
44+
</button>
45+
46+
<div className='page-number'>
47+
<input
48+
type='text'
49+
className='current-page'
50+
onBlur={event => { this.goToPage(event.target.value); event.target.value = ''; }}
51+
onKeyDown={event => { if (event.keyCode === KEY_CODES.ENTER) { event.currentTarget.blur(); } }}
52+
placeholder={(page_current + 1).toString()}
53+
defaultValue=''
54+
>
55+
</input>
56+
57+
{paginator.lastPage !== undefined ? ' / ' : ''}
58+
59+
{paginator.lastPage !== undefined ? <div className='last-page'>
60+
{paginator.lastPage + 1}
61+
</div> : ''}
62+
</div>
63+
64+
<button
65+
className='next-page'
66+
onClick={paginator.loadNext}
67+
disabled={!paginator.hasNext()} >
68+
<FontAwesomeIcon icon='angle-right' />
69+
</button>
70+
71+
<button
72+
className='last-page'
73+
onClick={paginator.loadLast}
74+
disabled={paginator.lastPage === undefined || paginator.isLast()}>
75+
<FontAwesomeIcon icon='angle-double-right' />
76+
</button>
77+
</div>
78+
);
79+
}
80+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import { IPaginator } from 'dash-table/derived/paginator';
2+
3+
export interface IPageNavigationProps {
4+
paginator: IPaginator;
5+
page_current: number;
6+
page_count: number | undefined;
7+
}

0 commit comments

Comments
 (0)