feat(web-core): add ignoreRoute option to table pagination and query builder filter (#10476)

This commit is contained in:
Thierry Goettelmann
2026-10-12 09:27:43 +02:00
committed by GitHub
parent b6b94a80b1
commit 641f988781
4 changed files with 32 additions and 13 deletions

View File

@@ -7,7 +7,9 @@ The composable uses index-based pagination instead of page numbers, enabling URL
## Storage
- Route query: `{id}.idx` stores start index
- LocalStorage: `{id}.per-page` stores "Show by" value (default: 50)
- LocalStorage: `{id}.per-page` stores "Show by" value (default: 24)
With `ignoreRoute: true`, the start index is kept in memory instead of the route query (e.g. for a table inside an overlay, which must not change the URL).
## Key Points
@@ -23,6 +25,9 @@ The composable uses index-based pagination instead of page numbers, enabling URL
// Basic usage
const { pageRecords, paginationBindings } = usePagination('items', items)
// Start index kept in memory
const { pageRecords, paginationBindings } = usePagination('items', items, { ignoreRoute: true })
// Template
<div v-for="item in pageRecords" :key="item.id">
{{ item.name }}

View File

@@ -1,7 +1,7 @@
import { useRouteQuery } from '@core/composables/route-query.composable.ts'
import { toComputed } from '@core/utils/to-computed.util.ts'
import { clamp, useLocalStorage } from '@vueuse/core'
import { computed, type MaybeRefOrGetter } from 'vue'
import { computed, type MaybeRefOrGetter, ref } from 'vue'
export type PaginationBindings = {
showBy: number
@@ -17,7 +17,7 @@ export type PaginationBindings = {
onPrevious: () => void
}
export function usePagination<T>(id: string, _records: MaybeRefOrGetter<T[]>) {
export function usePagination<T>(id: string, _records: MaybeRefOrGetter<T[]>, options?: { ignoreRoute?: boolean }) {
const records = toComputed(_records)
const showBy = useLocalStorage(`${id}.per-page`, 24)
@@ -33,11 +33,22 @@ export function usePagination<T>(id: string, _records: MaybeRefOrGetter<T[]>) {
return Math.floor(index / pageSize.value) * pageSize.value
}
const startIndex = useRouteQuery<number>(`${id}.idx`, {
defaultQuery: '0',
toData: value => toStartIndex(value),
toQuery: value => toStartIndex(value).toString(10),
})
function useLocalStartIndex() {
const localStartIndex = ref(0)
return computed({
get: () => toStartIndex(localStartIndex.value),
set: value => (localStartIndex.value = toStartIndex(value)),
})
}
const startIndex = options?.ignoreRoute
? useLocalStartIndex()
: useRouteQuery<number>(`${id}.idx`, {
defaultQuery: '0',
toData: value => toStartIndex(value),
toQuery: value => toStartIndex(value).toString(10),
})
const endIndex = computed(() => Math.min(startIndex.value + pageSize.value - 1, records.value.length - 1))

View File

@@ -211,10 +211,11 @@ const schema = useQueryBuilderSchema<User>({...})
// - Filters your items in real-time
// - Handles invalid filter expressions gracefully
const { items: filteredItems, filter } = useQueryBuilderFilter(
'users', // Unique ID (used in URL)
'users', // Unique ID (used in URL, unless ignoreRoute is true)
() => items.value, // Your data source
{
initialFilter: 'name:John' // Optional: pre-set filter
initialFilter: 'name:John', // Optional: pre-set filter
ignoreRoute: true, // Optional: keep the filter in memory instead of the URL
}
)

View File

@@ -1,7 +1,7 @@
import { toComputed } from '@core/utils/to-computed.util.ts'
import { useRouteQuery } from '@vueuse/router'
import { parse } from 'complex-matcher'
import { computed, type ComputedRef, type MaybeRefOrGetter, type Ref } from 'vue'
import { computed, type ComputedRef, type MaybeRefOrGetter, ref, type Ref } from 'vue'
export type UseQueryBuilderFilterReturn<TSource> = {
items: ComputedRef<TSource[]>
@@ -11,9 +11,11 @@ export type UseQueryBuilderFilterReturn<TSource> = {
export function useQueryBuilderFilter<TSource>(
id: string,
sourcesRaw: MaybeRefOrGetter<TSource[]>,
options?: { initialFilter?: string }
options?: { initialFilter?: string; ignoreRoute?: boolean }
): UseQueryBuilderFilterReturn<TSource> {
const filter = useRouteQuery(`qb.${id}`, options?.initialFilter ?? '')
const initialFilter = options?.initialFilter ?? ''
const filter = options?.ignoreRoute ? ref(initialFilter) : useRouteQuery(`qb.${id}`, initialFilter)
const sources = toComputed(sourcesRaw)