Ga naar hoofdinhoud

useListNavigation

Gives a detail page next and previous within the list the record was opened from.

A handler working a queue of forty opens the fourth case, reads it, and wants the fifth. Today that is back, find your place, click. Frappe Helpdesk keeps get_navigation_tickets, get_navigation_filters and get_navigation_order_by together for the reason this composable exists: "the next case" is meaningless until you know next in which list, filtered how and sorted how.

Usage​

import { useListNavigation } from '@conduction/nextcloud-vue'

const nav = reactive(useListNavigation({
route: useRoute(),
router: useRouter(),
currentId: toRef(props, 'objectId'),
objectType: 'case',
}))
<CnDetailPage
:listNavigation="nav"
:previousTo="nav.previousRoute"
:nextTo="nav.nextRoute"
@next-record="nav.goNext"
@previous-record="nav.goPrevious" />

previousRoute and nextRoute make the two controls real links. The link navigates by itself and the page then emits its step event with { event, to }; goNext and goPrevious recognise that payload and do not push again.

CnPageRenderer puts the list context into the record's address for you when the row was opened from a manifest index page. Nothing to wire.

Options​

OptionTypeDescription
routeObject | RefThe current route. The list context is read from its query.
routerObjectThe router. Without one, goNext and goPrevious resolve the id and do not navigate.
currentIdString | RefThe record open now.
objectTypeStringObject type slug, for the default fetcher.
objectStoreObjectAn object store, for the default fetcher.
fetchListFunctionLoads the list. Receives API params, returns records or ids. Overrides the store fetcher.
rowKeyStringField a record's id is read from. Defaults to id.
limitNumberHow many records of the list to hold. Defaults to 200.

What it returns​

KeyTypeDescription
availableComputedRef<boolean>Whether to offer the controls at all.
position, totalComputedRef<number>Where this record sits, and how long the list is.
isFirst, isLastComputedRef<boolean>Whether this is either end of the list.
hasNext, hasPreviousComputedRef<boolean>Whether there is a record to step to.
nextRoute, previousRouteComputedRef<object | null>Router location of that record, keeping the list context; null at either end. For CnDetailPage's nextTo / previousTo.
goNext, goPreviousFunctionOpen that record. Returns its id, or null at either end. Given a payload with a to (a link already navigated), returns the id without pushing.
neighboursComputedRef<object>The full shape: { position, total, previousId, nextId, isFirst, isLast, known }.
contextComputedRef<object | null>The list the address names, or null.
loading, failedRef<boolean>The load's state.
refreshFunctionReload the list.

The refusals​

Three cases offer nothing, and each is deliberate. A next button that steps somewhere the reader never chose is worse than no next button.

  • A link carrying no list context. No request is made and neither control renders, rather than inferring an order from an unfiltered fetch.
  • A record the list does not hold. The list has moved on, or the record is on another page of it. Offering a next from a position nobody knows would step somewhere arbitrary.
  • A list that could not be read. The controls stay away instead of reporting "1 of 0".

The first and the last record say so rather than wrapping. A next button on the last case that silently returns to the first is a handler who believes they are still working forwards through a queue they already finished.

A reload keeps the queue​

The context lives in the route, not in a store, so a reload rebuilds the navigation from the address alone. Stepping through a list does not refetch it: only a change to the list the address names does.

Next​

Give the reader somewhere to step from: turn on the split view and the list never leaves the screen.