Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/sun0fabeach/vue-use-paginator
Vue 3 use-hook to reactively paginate data and arrange paginator buttons
https://github.com/sun0fabeach/vue-use-paginator
Last synced: about 2 months ago
JSON representation
Vue 3 use-hook to reactively paginate data and arrange paginator buttons
- Host: GitHub
- URL: https://github.com/sun0fabeach/vue-use-paginator
- Owner: Sun0fABeach
- License: mit
- Created: 2021-11-28T21:14:26.000Z (about 3 years ago)
- Default Branch: master
- Last Pushed: 2024-05-30T09:01:55.000Z (8 months ago)
- Last Synced: 2024-09-12T11:53:00.905Z (4 months ago)
- Language: TypeScript
- Homepage:
- Size: 254 KB
- Stars: 18
- Watchers: 2
- Forks: 3
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# vue-use-paginator
Vue 3 composition API hook function to reactively paginate data and arrange paginator buttons. Completely renderless.
## Demo
* [Live demo](https://demo-vue-use-paginator.netlify.app/)
* [Demo code](https://github.com/Sun0fABeach/demo-vue-use-paginator/blob/master/src/components/Demo.vue)## Installation
```shell
$ npm install vue-use-paginator
```## Basic Setup
```html
import usePaginator from 'vue-use-paginator'
const {
page,
pageSize,
numPages,
numItems,
numButtons,
slice,
buttons,
hasPrev,
hasNext,
goStart,
goPrev,
goNext,
goEnd,
} = usePaginator({
pageSize: 10,
numItems: 70,
numButtons: 5,
})```
## Details
### Hook API
Function `usePaginator` returns an object of type [`IPagination`](<#user-content-definitions> "IPagination") which contains the following reactive data plus some convenience functions. You can initialize `page`, `pageSize`, `numItems` and `numButtons` by passing an object of type [`IOptions`](<#user-content-definitions> "IOptions"). Otherwise, default initial values will be used.
| Name | Type | Description
| -------------- | ---------------------------------- | -----------
| `page` | `Ref` | Current active page (default initial value: 1)
| `pageSize` | `Ref` | Size of each page (default initial value: 5)
| `numItems` | `Ref` | Total number of items to paginate (default initial value: 0)
| `numButtons` | `Ref` | Number of paginator buttons to display (default initial value: 5)
| `numPages` | `ComputedRef` | Total number of pages
| `slice` | `ComputedRef<[number, number]>` | Tuple containing start and end index delimiting the currently active page (0 based, end index is exclusive). For example, given you are on page 2, `pageSize` is 10 and `numItems` is greater than or equal to 20, `slice` will be `[10, 20]`.
| `buttons` | `ComputedRef` | Array of objects usable for displaying paginator buttons (details below)
| `hasPrev` | `ComputedRef` | Whether the currently active page is the first page
| `hasNext` | `ComputedRef` | Whether the currently active page is the last page
| `goPrev` | `() => number` | Go to next page
| `goNext` | `() => number` | Go to previous page
| `goStart` | `() => 1` | Go to first page
| `goEnd` | `() => number` | Go to last page* `page`, `pageSize`, `numItems`, as well as `numButtons` are writable refs that will cause the other reactive properties to adjust when changed. Once you know how many items to paginate, you need to set `numItems` at least.
* You can move to another page by either calling `goPrev`, `goNext`, `goStart`, `goEnd`, or by assigning to `page` directly. Note that assigning a value outside of 1 and `numPages` will be ignored.### Paginator buttons
When displaying paginator buttons, you often don't have enough slots for each page and therefore need to use a placeholder like '...'. Calculating the positions of these placeholders is not trivial. Luckily, `buttons` is an array of [`IPaginatorButton`](<#user-content-definitions> "IPaginatorButton") where each item contains the following properties to help you out.
| Name | Type | Description
| ---------- | ---------- | -----------
| `page` | `number` | The page to navigate to when clicking this button
| `active` | `boolean` | Whether this button shows the currently active page
| `ellipsis` | `boolean` | Whether this button is a placeholder for omitted pages#### Template example
Here is a minimal example how you could write your paginator markup.
```vue
{{ '<<' }}
{{ '<' }}
{{ button.ellipsis ? '...' : button.page }}
{{ '>' }}
{{ '>>' }}
```Notice how certain classes and texts are set based on the values of `hasPrev`, `hasNext`, `button.active` and `button.ellipsis`. How you style these elements is completely up to you.
### API integration
This library doesn't make any assumptions about whether you paginate in the frontend or call a paginated endpoint.
If you paginate in the frontend, just assign the length of your collection to `numItems` and use the values from `slice` to slice out the items to display for your current page.
If you call a paginated endpoint, it needs to tell you the total number of items in order to set `numItems`. You can then use `slice` or `page`/`pageSize` to fetch a page. You will normally want to set up a watcher in order to fetch a new page when `page` or `pageSize` changes.
```typescript
watch([page, pageSize], ([newPage, newPageSize]) => {
fetchPage(newPage, newPageSize);
})
```### Types
#### Definitions
```typescript
interface IOptions {
page?: number | Ref
pageSize?: number | Ref
numItems?: number | Ref
numButtons?: number | Ref
}interface IPagination {
page: Ref
pageSize: Ref
numItems: Ref
numButtons: Ref
numPages: ComputedRef
slice: ComputedRef<[number, number]>
buttons: ComputedRef
hasPrev: ComputedRef
hasNext: ComputedRef
goPrev: () => number
goNext: () => number
goStart: () => 1
goEnd: () => number
}interface IButton {
page: number
}interface IPageButton extends IButton {
active: boolean
ellipsis: false
}interface IEllipsisButton extends IButton {
active: false
ellipsis: true
}type IPaginatorButton = IPageButton | IEllipsisButton
```#### Importing Types
```typescript
import { IOptions, IPagination, IPaginatorButton } from 'vue-use-paginator'
```