Skip to content

Commit 91af250

Browse files
committed
Document FeathersVuexPagination in composition API
1 parent e94a8e2 commit 91af250

File tree

1 file changed

+206
-0
lines changed

1 file changed

+206
-0
lines changed

docs/composition-api.md

Lines changed: 206 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -298,6 +298,212 @@ interface UseGetData {
298298
}
299299
```
300300
301+
## FeathersVuexPagination
302+
303+
As of version `3.8.0`, Feathers-Vuex includes the `FeathersVuexPagination` renderless component. This component pairs with the [`useFind` utility](#usefind) to simplify handling server-side pagination. If you use the FeathersVuex Vue plugin, the `FeathersVuexPagination` component is registered as a global component. Since it's a renderless component, you'll need to supply your own UI to the default slot.
304+
305+
### Usage Steps
306+
307+
The steps to using the `FeathersVuexPagination` component include
308+
309+
1. Create a `pagination` ref containing an object with `$limit` and `$skip` properties.
310+
2. Create a `params` computed property. Be sure to include a `query` object and `paginate: true` in the params. It's also recommended that you use a `qid` to identify the component that you're using, otherwise pagination data could mix with other parts of the UI and create an inconsistent experience.
311+
3. Merge the `pagination` into the `params.query`.
312+
4. Pass the `params` object to the `useFind` utility.
313+
5. Pull the `items` array and `latestQuery` object from `useFind`'s return value.
314+
6. Make the `items`, `latestQuery`, and `pagination` available to the component's template by returning them in the setup method.
315+
7. Provide the above two variables to the `FeathersVuexPagination` component as props.
316+
8. Provide a UI inside the default slot, binding to variables and desired events.
317+
318+
### Props
319+
320+
The `FeathersVuexPagination` component only accepts two props.
321+
322+
- `v-model` (or `value`): Receives the `pagination` object, which must contain the `$limit` and `$skip` properties.
323+
- `latest-query`, which receives the `latestQuery` object returned by the `useFind` utility.
324+
325+
### Default Slot Scope
326+
327+
The following variables and functions are provided by the default slot:
328+
329+
- `currentPage` {Number} The current page number, based on the current `$limit` and `$skip` values provided to the `v-model`.
330+
- `pageCount` {Number} If the response from the API server includes a `total` attribute, the `pageCount` will be the total number of pages, based on the current value of `$limit`.
331+
- `canPrev` {Boolean} Will be true if not on the first page (can go to a previous page). This value is useful for enabling/disabling a button in the UI, if you desire to give that kind of feedback to the user.
332+
- `canNext` {Boolean} Will be true if not on the last page (can go to a next page). This value is useful for enabling/disabling a button in the UI, if you desire to give that kind of feedback to the user.
333+
- `toStart` {Function} When called, will move to the first page.
334+
- `toEnd` {Function} When called, will move to the last page.
335+
- `toPage(n: number)` {Function} When called with a page number as its first argument, will move to that page number. If the page number is greater than the total number of pages, will go to the last page. If the page number is less than 0, will go to the first page.
336+
- `prev` {Function} When called, moves to the previous page. Will not go below page 1.
337+
- `next` {Function} When called, moves tot the next page. Will not go past the last page.
338+
339+
### Example
340+
341+
Here is an example of how to use it. It assumes that you have a `/listings` service with a `Listing` model. The next code example below this one shows the `PaginationUi` component. Note that not all slot scope variables and functions are required. To implement basic pagination, only the `currentPage`, `pageCount`, `next`, and `prev` values are really necessary. The other slot scope values allow providing a customized pagination experience.
342+
343+
```html
344+
<template>
345+
<div>
346+
<!-- 7. ^ -->
347+
<FeathersVuexPagination v-model="pagination" :latest-query="latestQuery">
348+
<!-- 8. ^ -->
349+
<template #default="{ currentPage, pageCount, toStart, toEnd, toPage, next, prev, canNext, canPrev }">
350+
<PaginationUi
351+
:current-page="currentPage"
352+
:page-count="pageCount"
353+
:can-prev="canPrev"
354+
:can-next="canNext"
355+
@to-start="toStart"
356+
@to-end="toEnd"
357+
@to-page="toPage"
358+
@next="next"
359+
@prev="prev"
360+
/>
361+
</template>
362+
</FeathersVuexPagination>
363+
364+
<!-- Results -->
365+
<div>
366+
<div v-for="item in items" :key="item._id">
367+
{{ item }}
368+
</div>
369+
</div>
370+
</div>
371+
</template>
372+
373+
<script>
374+
import { ref, computed, watch } from '@vue/composition-api'
375+
import { models, useFind, FeathersVuexPagination } from 'feathers-vuex'
376+
import PaginationUi from './PaginationUi.vue'
377+
378+
export default {
379+
name: 'PaginationExample',
380+
components: {
381+
FeathersVuexPagination,
382+
PaginationUi
383+
},
384+
setup(props, context) {
385+
const { Listing } = models.api
386+
387+
// 1.^
388+
const pagination = ref({
389+
$limit: 20,
390+
$skip: 0
391+
})
392+
// 2.^
393+
const params = computed(() => {
394+
const query = {}
395+
// 3.^
396+
Object.assign(query, pagination.value)
397+
398+
return { query, qid: 'listingsPage', paginate: true }
399+
})
400+
// 4.^
401+
const data = useFind({ model: Listing, params: params })
402+
403+
// 5.^ (can be merged into previous line)
404+
const { items, latestQuery } = data
405+
406+
// 6.^
407+
return { items, pagination, latestQuery }
408+
}
409+
}
410+
</script>
411+
```
412+
413+
As promised, here is the example code for the `PaginationUi` component used above. It includes some TailwindCSS utility classes in the markup in order to show how one might use the `canPrev` and `canNext` properties. Keep in mind that this is just an example. You can provide whatever experience you want for your users by creating your own component.
414+
415+
```html
416+
<template>
417+
<div class="flex flex-row items-center mt-2">
418+
<button
419+
type="button"
420+
class="rounded py-0.5 flex flex-row items-center justify-center w-24 mr-1"
421+
:class="[
422+
canPrev
423+
? 'bg-gray-600 text-white'
424+
: 'bg-gray-400 text-gray-500 cursor-not-allowed'
425+
]"
426+
:disabled="!canPrev"
427+
@click="e => $emit('prev', e)"
428+
>
429+
<ChevronLeftIcon />
430+
<p class="pr-2">Previous</p>
431+
</button>
432+
433+
<button
434+
type="button"
435+
class="bg-gray-600 text-white rounded py-0.5 flex flex-row items-center justify-center w-24 mr-1"
436+
@click="e => $emit('to-start', e)"
437+
>
438+
<p class="pr-2">To Start</p>
439+
</button>
440+
441+
<div class="flex flex-grow justify-center items-center">
442+
Page
443+
<input
444+
v-model.number="currentPage"
445+
type="text"
446+
class="w-12 rounded py-0.5 mx-1.5 dark:bg-gray-900 text-center"
447+
/>
448+
of {{ pageCount }}
449+
</div>
450+
451+
<button
452+
type="button"
453+
class="bg-gray-600 text-white rounded py-0.5 flex flex-row items-center justify-center w-24 mr-1"
454+
@click="e => $emit('to-end', e)"
455+
>
456+
<p class="pr-2">To End</p>
457+
</button>
458+
459+
<button
460+
type="button"
461+
class="rounded py-0.5 flex flex-row items-center justify-center w-24"
462+
:class="[
463+
canNext
464+
? 'bg-gray-600 text-white'
465+
: 'bg-gray-400 text-gray-500 cursor-not-allowed'
466+
]"
467+
:disabled="!canNext"
468+
@click="e => $emit('next', e)"
469+
>
470+
<div class="w-12">Next</div>
471+
<ChevronRightIcon />
472+
</button>
473+
</div>
474+
</template>
475+
476+
<script>
477+
import { ChevronLeftIcon, ChevronRightIcon } from 'vue-feather-icons'
478+
479+
export default {
480+
name: 'SidebarPagination',
481+
components: {
482+
ChevronLeftIcon,
483+
ChevronRightIcon
484+
},
485+
props: {
486+
currentPage: {
487+
type: Number,
488+
required: true
489+
},
490+
pageCount: {
491+
type: Number,
492+
required: true
493+
},
494+
canPrev: {
495+
type: Boolean,
496+
required: true
497+
},
498+
canNext: {
499+
type: Boolean,
500+
required: true
501+
}
502+
}
503+
}
504+
</script>
505+
```
506+
301507
## Patterns & Examples
302508

303509
### Server-Side Pagination

0 commit comments

Comments
 (0)