Skip to content

Instantly share code, notes, and snippets.

@naramdash
Last active July 7, 2020 10:23
Show Gist options
  • Save naramdash/ed38c558ab743e06ed3bdedfc8cff35a to your computer and use it in GitHub Desktop.
Save naramdash/ed38c558ab743e06ed3bdedfc8cff35a to your computer and use it in GitHub Desktop.
React Material-UI Pagination Component with Displayed-Page-Range style using Typescript & Material-UI
import React, { useMemo, FC } from 'react'
import { Box, Button, makeStyles } from '@material-ui/core'
import { SkipPrevious, SkipNext, NavigateBefore, NavigateNext } from '@material-ui/icons'
import classnames from 'classnames'
function range(start: number, stop: number, step: number) {
return Array.from({ length: (stop - start) / step + 1 }, (_, i) => start + i * step)
}
interface PaginationParams {
activePage: number
onChangeActivePage: (activePage: number) => any
itemsCountPerPage: number
totalItemsCount: number
pageRangeDisplayed: number
}
const Pagination: FC<PaginationParams> = ({
activePage,
onChangeActivePage,
itemsCountPerPage,
totalItemsCount,
pageRangeDisplayed,
}) => {
const styles = useStyles()
const { displayedPages, totalPageCount, startDisplayedPage, endDisplayedPage } = useMemo(() => {
const totalPageCount = Math.ceil(totalItemsCount / itemsCountPerPage)
const startDisplayedPage =
Math.floor((activePage - 1) / pageRangeDisplayed) * pageRangeDisplayed + 1
const assumedEndDisplayedPage =
Math.floor((activePage - 1) / pageRangeDisplayed) * pageRangeDisplayed + pageRangeDisplayed
const endDisplayedPage =
assumedEndDisplayedPage > totalPageCount ? totalPageCount : assumedEndDisplayedPage
const displayedPages = range(startDisplayedPage, endDisplayedPage, 1)
return {
displayedPages,
totalPageCount,
startDisplayedPage,
endDisplayedPage,
}
}, [activePage, itemsCountPerPage, totalItemsCount, pageRangeDisplayed])
return (
<Box display="flex" flexDirection="row" justifyItems="">
<Button
variant="outlined"
className={styles.skipButton}
onClick={() => onChangeActivePage(1)}
>
<SkipPrevious />
</Button>
<Button
variant="outlined"
className={styles.skipButton}
onClick={() => {
if (startDisplayedPage - pageRangeDisplayed > 0)
onChangeActivePage(startDisplayedPage - pageRangeDisplayed)
else onChangeActivePage(1)
}}
>
<NavigateBefore />
</Button>
{displayedPages.map((displayedPage: number) => (
<Button
key={displayedPage}
className={classnames([
styles.pageButton,
{ [styles.selectedPageButton]: activePage === displayedPage },
])}
onClick={() => onChangeActivePage(displayedPage)}
>
{displayedPage}
</Button>
))}
<Button
variant="outlined"
className={styles.skipButton}
onClick={() => {
if (endDisplayedPage + 1 > totalPageCount) onChangeActivePage(totalPageCount)
else onChangeActivePage(endDisplayedPage + 1)
}}
>
<NavigateNext />
</Button>
<Button
variant="outlined"
className={styles.skipButton}
onClick={() => onChangeActivePage(totalPageCount)}
>
<SkipNext />
</Button>
</Box>
)
}
const useStyles = makeStyles((theme) => ({
skipButton: {
minHeight: 0,
minWidth: 0,
padding: 4,
margin: '0 5px 0 5px',
},
pageButton: {
minWidth: 25,
margin: '0 5px 0 5px',
color: '#3A3A3A',
},
selectedPageButton: {
backgroundColor: theme.palette.primary.main,
color: '#FFFFFF',
},
}))
export default Pagination
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment