npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

vue-use-paginator

v0.4.1

Published

Vue use-hook for renderless pagination logic

Downloads

771

Readme

vue-use-paginator

Vue 3 composition API hook function to reactively paginate data and arrange paginator buttons. Completely renderless.

Demo

Installation

$ npm install vue-use-paginator

Basic Setup

<script setup lang="ts">
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,
})
</script>

Details

Hook API

Function usePaginator returns an object of type 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. Otherwise, default initial values will be used.

| Name | Type | Description | -------------- | ---------------------------------- | ----------- | page | Ref<number> | Current active page (default initial value: 1) | pageSize | Ref<number> | Size of each page (default initial value: 5) | numItems | Ref<number> | Total number of items to paginate (default initial value: 0) | numButtons | Ref<number> | Number of paginator buttons to display (default initial value: 5) | numPages | ComputedRef<number> | 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<IPaginatorButton[]> | Array of objects usable for displaying paginator buttons (details below) | hasPrev | ComputedRef<boolean> | Whether the currently active page is the first page | hasNext | ComputedRef<boolean> | 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 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.

<ol>
  <li :class="{ disabled: !hasPrev }" @click="goStart">
    {{ '<<' }}
  </li>
  <li :class="{ disabled: !hasPrev }" @click="goPrev">
    {{ '<' }}
  </li>
  <li
    v-for="button in buttons"
    :key="button.page"
    :class="{ 'current-page': button.active }"
    @click="page = button.page"
  >
    {{ button.ellipsis ? '...' : button.page }}
  </li>
  <li :class="{ disabled: !hasNext }" @click="goNext">
    {{ '>' }}
  </li>
  <li :class="{ disabled: !hasNext }" @click="goEnd">
    {{ '>>' }}
  </li>
</ol>

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.

watch([page, pageSize], ([newPage, newPageSize]) => {
  fetchPage(newPage, newPageSize);
})

Types

Definitions

interface IOptions {
  page?: number | Ref<number>
  pageSize?: number | Ref<number>
  numItems?: number | Ref<number>
  numButtons?: number | Ref<number>
}

interface IPagination {
  page: Ref<number>
  pageSize: Ref<number>
  numItems: Ref<number>
  numButtons: Ref<number>
  numPages: ComputedRef<number>
  slice: ComputedRef<[number, number]>
  buttons: ComputedRef<IPaginatorButton[]>
  hasPrev: ComputedRef<boolean>
  hasNext: ComputedRef<boolean>
  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

import { IOptions, IPagination, IPaginatorButton } from 'vue-use-paginator'