Skip to content

Commit a1b1ea4

Browse files
Merge branch 'master' into patch-7
2 parents 43de5d6 + dacf998 commit a1b1ea4

21 files changed

+1784
-976
lines changed

docs/2.0-major-release.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,8 @@ I have not been able to find a diffing algorithm that works equally well acroos
163163

164164
## Model Classes: BYOD (Bring Your Own Diffing)
165165

166+
> Note: As of `[email protected]`, you can also pass `params.data` to the patch object to implement partial patching on objects. You might choose to use `params.data` instead of `diffOnPatch`.
167+
166168
First, why do any diffing? On the API server, an `update` request replaces an entire object, but a `patch` request only overwrites the attributes that are provided in the data. For services with simple schemas, it doesn't really matter. But if your schema grows really large, it can be supportive to only send the updates instead of the entire object.
167169

168170
A new `diffOnPatch` method is available to override in your extended models. `diffOnPatch` gets called just before sending the data to the API server. It gets called with the data and must return the diffed data. By default, it is set to `diffOnPatch: data => data`.

docs/3.0-major-release.md

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,25 @@ Version 3.0 of Feathers-Vuex is the Vue Composition API release! There were qui
1616

1717
And now it has become the best way to perform queries with Feathers-Vuex. To find out how to take advantage of the new functionality in your apps, read the [Feather-Vuex Composition API docs](./composition-api.md).
1818

19+
## Partial data on patch <Badge text="3.9.0+" />
20+
As of version 3.9.0, you can provide an object as `params.data`, and Feathers-Vuex will use `params.data` as the patch data. This change was made to the service-module, itself, so it will work for `patch` across all of feathers-vuex. Here's an example of patching with partial data:
21+
22+
```js
23+
import { models } from 'feathers-vuex'
24+
const { Todo } = models.api
25+
26+
const todo = new Todo({ description: 'Do Something', isComplete: false })
27+
28+
todo.patch({ data: { isComplete: true } })
29+
30+
// also works for patching with instance.save
31+
todo.save({ data: { isComplete: true } })
32+
```
33+
34+
## FeathersVuexPagination Component <Badge text="3.8.0+" />
35+
36+
To assist with Server Side Pagination support, Feathers-Vuex now includes the `<FeathersVuexPagination>` component. It's a renderless component that removes the boilerplate behind handling pagination in the UI. Read about it in the [Composition API Docs](/composition-api.html#feathersvuexpagination).
37+
1938
## Custom Handling for Feathers Events <Badge text="3.1.0+" />
2039

2140
Version 3.1 of Feathers-Vuex enables ability to add custom handling for each of the FeathersJS realtime events. You can read more about it in the [Service Plugin: Events](./service-plugin.md#service-events) docs.

docs/common-patterns.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ You can set `debug: true` in the options to enable some logging to assist with d
1212

1313
## Use the `<FeathersVuexFind>` and `<FeathersVuexGet>` components
1414

15-
Using the new `<FeathersVuexFind>` and `<FeathersVuexGet>` components provides concise access to the best features of `feathers-vuex`, including live queries, reactive lists, custom pagination tracking per component, and fall-through cacheing of local data in the Vuex store. Check out the [Renderless Data Components](./components.html) docs for more details.
15+
Using the new `<FeathersVuexFind>` and `<FeathersVuexGet>` components provides concise access to the best features of `feathers-vuex`, including live queries, reactive lists, custom pagination tracking per component, and fall-through cacheing of local data in the Vuex store. Check out the [Renderless Data Components](./data-components.html) docs for more details.
1616

1717
## Use the `makeFindMixin` and `makeGetMixin` utilities
1818

docs/composition-api.md

Lines changed: 215 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -132,16 +132,16 @@ Notice the `tutorialsData` in the previous example. You can see that there's an
132132
```ts
133133
interface UseFindData {
134134
items: Ref<any>
135+
paginationData: Ref<object>
135136
servicePath: Ref<string>
136-
isFindPending: Ref<boolean>
137-
haveBeenRequestedOnce: Ref<boolean>
138-
haveLoaded: Ref<boolean>
139-
isLocal: Ref<boolean>
140137
qid: Ref<string>
138+
isPending: Ref<boolean>
139+
haveBeenRequested: Ref<boolean>
140+
haveLoaded: Ref<boolean>
141+
error: Ref<Error>
141142
debounceTime: Ref<number>
142143
latestQuery: Ref<object>
143-
paginationData: Ref<object>
144-
error: Ref<Error>
144+
isLocal: Ref<boolean>
145145
find: Function
146146
}
147147
```
@@ -298,6 +298,215 @@ 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+
:value="currentPage"
445+
type="number"
446+
:min="1"
447+
:max="pageCount"
448+
class="w-12 rounded py-0.5 mx-1.5 dark:bg-gray-900 text-center"
449+
@input="event => $emit('to-page', event.target.value)"
450+
/>
451+
of {{ pageCount }}
452+
</div>
453+
454+
<button
455+
type="button"
456+
class="bg-gray-600 text-white rounded py-0.5 flex flex-row items-center justify-center w-24 mr-1"
457+
@click="e => $emit('to-end', e)"
458+
>
459+
<p class="pr-2">To End</p>
460+
</button>
461+
462+
<button
463+
type="button"
464+
class="rounded py-0.5 flex flex-row items-center justify-center w-24"
465+
:class="[
466+
canNext
467+
? 'bg-gray-600 text-white'
468+
: 'bg-gray-400 text-gray-500 cursor-not-allowed'
469+
]"
470+
:disabled="!canNext"
471+
@click="e => $emit('next', e)"
472+
>
473+
<div class="w-12">Next</div>
474+
<ChevronRightIcon />
475+
</button>
476+
</div>
477+
</template>
478+
479+
<script>
480+
import { ChevronLeftIcon, ChevronRightIcon } from 'vue-feather-icons'
481+
482+
export default {
483+
name: 'SidebarPagination',
484+
components: {
485+
ChevronLeftIcon,
486+
ChevronRightIcon
487+
},
488+
props: {
489+
currentPage: {
490+
type: Number,
491+
required: true
492+
},
493+
pageCount: {
494+
type: Number,
495+
required: true
496+
},
497+
canPrev: {
498+
type: Boolean,
499+
required: true
500+
},
501+
canNext: {
502+
type: Boolean,
503+
required: true
504+
}
505+
}
506+
}
507+
</script>
508+
```
509+
301510
## Patterns & Examples
302511

303512
### Server-Side Pagination

docs/data-components.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ import { FeathersVuexFind, FeathersVuexGet } from 'feathers-vuex'
126126

127127
// in your component
128128
components: {
129-
FeathersVuexData,
129+
FeathersVuexFind,
130130
FeathersVuexGet
131131
}
132132

0 commit comments

Comments
 (0)