mirror of
https://github.com/vatesfr/xen-orchestra.git
synced 2026-11-09 17:06:13 -06:00
feat(web-core): add ignoreRoute option to table pagination and query builder filter (#10476)
This commit is contained in:
committed by
GitHub
parent
b6b94a80b1
commit
641f988781
@@ -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 }}
|
||||
|
||||
@@ -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))
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user