There are no notes for this item.
Prop | Required? | Type | Default | Description |
---|---|---|---|---|
onPageSelect | Yes | func | ||
page | Yes | number | ||
pages | Yes | number | ||
maxPageListLength | No | number | 10 | |
showLastPage | No | bool |
<div id="reactMount" data-tpl="pagination">
<div class="va-pagination"><span class="va-pagination-prev"><a aria-label="Previous page"><abbr title="Previous">Prev</abbr></a></span>
<div class="va-pagination-inner"><a class="" aria-label="Page 1">1</a><a class="va-pagination-active" aria-label="Page 2">2</a><a class="" aria-label="Page 3">3</a> </div><span class="va-pagination-next"><a aria-label="Next page">Next</a></span></div>
</div>
<script>
window.currentProps = {
"package": {
"name": "department-of-veteran-affairs/jean-pants",
"version": "0.1.0"
},
"assetPath": "/design-system/",
"isProduction": true,
"componentSourcePath": "./Pagination.jsx",
"page": 2,
"pages": 3,
"maxPageListLength": 3,
"showLastPage": true
}
</script>
import React from 'react';
import Pagination from './Pagination';
export default function PaginationExample(props) {
return (
<Pagination
onPageSelect={(e) => {}}
page={props.page}
pages={props.pages}
maxPageListLength={props.maxPageListLength}
showLastPage={props.showLastPage}
/>
);
}
package:
name: department-of-veteran-affairs/jean-pants
version: 0.1.0
assetPath: /design-system/
isProduction: true
componentSourcePath: ./Pagination.jsx
page: 2
pages: 3
maxPageListLength: 3
showLastPage: true
/* eslint-disable */
import PropTypes from 'prop-types';
import React from 'react';
import classNames from 'classnames';
import range from 'lodash/fp/range';
class Pagination extends React.Component {
constructor(props) {
super(props);
this.next = this.next.bind(this);
this.prev = this.prev.bind(this);
this.last = this.last.bind(this);
this.pageNumbers = this.pageNumbers.bind(this);
}
next() {
let nextPage;
if (this.props.pages > this.props.page) {
nextPage = (
<a aria-label="Next page" onClick={() => {this.props.onPageSelect(this.props.page + 1);}}>
Next
</a>
);
}
return nextPage;
}
prev() {
let prevPage;
if (this.props.page > 1) {
prevPage = (
<a aria-label="Previous page" onClick={() => {this.props.onPageSelect(this.props.page - 1);}}>
<abbr title="Previous">Prev</abbr>
</a>
);
}
return prevPage;
}
last() {
const {
maxPageListLength,
page: currentPage,
pages: totalPages,
showLastPage
} = this.props;
let lastPage;
if (showLastPage && currentPage < totalPages - maxPageListLength + 1) {
lastPage = (
<span>
<a aria-label="...">
...
</a>
<a aria-label="Last page" onClick={() => {this.props.onPageSelect(totalPages);}}>
{totalPages}
</a>
</span>
);
}
return lastPage;
}
pageNumbers() {
const {
maxPageListLength,
page: currentPage,
pages: totalPages,
showLastPage
} = this.props;
// Make space for "... (last page number)" if not in range of the last page.
const showEllipsisAndLastPage =
showLastPage &&
currentPage < totalPages - maxPageListLength + 1;
const limit = showEllipsisAndLastPage
? maxPageListLength - 2
: maxPageListLength;
let end;
let start;
// If there are more pages returned than the limit to show
// cap the upper range at limit + the page number.
if (totalPages > limit) {
start = currentPage;
end = limit + currentPage;
// treat the last pages specially
if (start >= totalPages - limit + 1) {
start = totalPages - limit + 1;
end = totalPages + 1;
}
} else {
start = 1;
end = totalPages + 1;
}
return range(start, end);
}
render() {
if (this.props.pages === 1) {
return <div/>;
}
const pageList = this.pageNumbers().map((pageNumber) => {
const pageClass = classNames({
'va-pagination-active': this.props.page === pageNumber
});
return (
<a
key={pageNumber}
className={pageClass}
aria-label={`Page ${pageNumber}`}
onClick={() => this.props.onPageSelect(pageNumber)}>
{pageNumber}
</a>
);
});
return (
<div className="va-pagination">
<span className="va-pagination-prev">{this.prev()}</span>
<div className="va-pagination-inner">
{pageList} {this.last()}
</div>
<span className="va-pagination-next">{this.next()}</span>
</div>
);
}
}
Pagination.propTypes = {
onPageSelect: PropTypes.func.isRequired,
page: PropTypes.number.isRequired,
pages: PropTypes.number.isRequired,
maxPageListLength: PropTypes.number.isRequired,
showLastPage: PropTypes.bool,
};
Pagination.defaultProps = {
maxPageListLength: 10,
};
export default Pagination;
import React from 'react';
import { shallow } from 'enzyme';
import { expect } from 'chai';
import Pagination from './Pagination';
import { axeCheck } from '../../../../lib/testing/helpers';
const props = {
onPageSelect: () => {},
};
describe('<Pagination>', () => {
it('should show all pages if there are fewer pages than the max', () => {
const tree = shallow(
<Pagination
{...props}
page={1}
pages={5}/>
);
const links = tree.find('a');
expect(links).to.have.length(6);
links.forEach((link, index) => {
if (index === 5) {
expect(link.text()).to.equal('Next');
} else {
const pageNumber = (index + 1).toString();
expect(link.text()).to.equal(pageNumber);
}
});
});
it('should show both "Prev" and "Next" if in a middle page', () => {
const tree = shallow(
<Pagination
{...props}
page={3}
pages={5}/>
);
const links = tree.find('a');
expect(links).to.have.length(7);
links.forEach((link, index) => {
if (index === 0) {
expect(link.text()).to.equal('Prev');
} else if (index === 6) {
expect(link.text()).to.equal('Next');
} else {
const pageNumber = index.toString();
expect(link.text()).to.equal(pageNumber);
}
});
});
it('should show "Prev" but not "Next" if on the last page', () => {
const tree = shallow(
<Pagination
{...props}
page={5}
pages={5}/>
);
const links = tree.find('a');
expect(links).to.have.length(6);
links.forEach((link, index) => {
if (index === 0) {
expect(link.text()).to.equal('Prev');
} else if (index === 6) {
expect(link.text()).to.equal('Next');
} else {
const pageNumber = index.toString();
expect(link.text()).to.equal(pageNumber);
}
});
});
it('should show the correct range of pages if the max is exceeded', () => {
const tree = shallow(
<Pagination
{...props}
page={5}
pages={20}/>
);
const links = tree.find('a');
expect(links).to.have.length(12);
links.forEach((link, index) => {
if (index === 0) {
expect(link.text()).to.equal('Prev');
} else if (index === 11) {
expect(link.text()).to.equal('Next');
} else {
const pageNumber = (index + 4).toString();
expect(link.text()).to.equal(pageNumber);
}
});
});
it('show the last page if enabled and there are more pages than max', () => {
const tree = shallow(
<Pagination
{...props}
page={3}
pages={15}
maxPageListLength={10}
showLastPage/>
);
const links = tree.find('a');
expect(links).to.have.length(12);
links.forEach((link, index) => {
if (index === 0) {
expect(link.text()).to.equal('Prev');
} else if (index === 9) {
expect(link.text()).to.equal('...');
} else if (index === 10) {
expect(link.text()).to.equal('15');
} else if (index === 11) {
expect(link.text()).to.equal('Next');
} else {
const pageNumber = (index + 2).toString();
expect(link.text()).to.equal(pageNumber);
}
});
});
it('should show a continuous list when within range of the last page', () => {
const tree = shallow(
<Pagination
{...props}
page={6}
pages={15}
maxPageListLength={10}
showLastPage/>
);
const links = tree.find('a');
expect(links).to.have.length(12);
links.forEach((link, index) => {
if (index === 0) {
expect(link.text()).to.equal('Prev');
} else if (index === 10) {
expect(link.text()).to.equal('15');
} else if (index === 11) {
expect(link.text()).to.equal('Next');
} else {
const pageNumber = (index + 5).toString();
expect(link.text()).to.equal(pageNumber);
}
});
});
it('should pass aXe check', () => {
return axeCheck(<Pagination
{...props}
page={3}
pages={5}/>
);
});
});