Skip to content

Commit 5f5d671

Browse files
committed
feat: add dropdown for selecting page size options in list view
1 parent f61689c commit 5f5d671

4 files changed

Lines changed: 100 additions & 4 deletions

File tree

adminforth/documentation/docs/tutorial/03-Customization/13-standardPagesTuning.md

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -319,6 +319,35 @@ export default {
319319
]
320320
```
321321

322+
### List Page Size Options
323+
You can define available pagination sizes using options.listPageSizeOptions. This allows users to choose how many records they want to see per page in the list view.
324+
```typescript title="./resources/apartments.ts"
325+
export default {
326+
resourceId: 'aparts',
327+
options: {
328+
...
329+
listPageSize: 10,
330+
//diff-add
331+
listPageSizeOptions: [10, 20, 50],
332+
}
333+
}
334+
]
335+
```
336+
337+
#### How it works
338+
- listPageSize defines the default number of records per page when the list is opened.
339+
- listPageSizeOptions defines the available page size options shown to the user.
340+
341+
For example: listPageSizeOptions: [10, 20, 50] will allow switching between 10 / 20 / 50 records per page.
342+
343+
#### UI behavior
344+
Page size switching is implemented via a select dropdown (select input) in the table pagination controls.
345+
- User opens the select
346+
- Chooses a value (e.g. 20)
347+
- Table reloads with the new page size
348+
> ☝️Notes
349+
If listPageSizeOptions is not provided, a default set of page sizes will be used. The selected value updates the table immediately and triggers a data refetch. This option works together with listPageSize, which defines both the default value and the available options at the same time.
350+
322351
### Virtual scroll
323352

324353
Set `options.listVirtualScrollEnabled` to true to enable virtual scrolling in the table. The default value is false. Enable this option if you need to display a large number of records on a single page.

adminforth/spa/src/components/ResourceListTable.vue

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -340,6 +340,20 @@
340340
</span>
341341
</template>
342342
</span>
343+
<div v-if="totalRows > 0 && pageSizeOptionsComputed?.length"
344+
class="flex items-center gap-2 ml-auto" >
345+
<span class="text-sm text-lightListTablePaginationHelpText dark:text-darkListTablePaginationHelpText">
346+
{{ $t('Rows per page') }}
347+
</span>
348+
<Select v-model="pageSizeInternal"
349+
:options="pageSizeOptionsComputed"
350+
:searchDisabled="true"
351+
class="text-sm w-[68px]"
352+
classesForInput="h-[34px] min-h-0 py-1 pl-2 pr-6 text-sm rounded-md cursor-pointer af-button-shadow
353+
bg-lightDropdownButtonsBackground text-lightDropdownButtonsText border-lightDropdownButtonsBorder
354+
dark:bg-darkDropdownButtonsBackground dark:text-darkDropdownButtonsText dark:border-darkDropdownButtonsBorder"
355+
/>
356+
</div>
343357
</div>
344358
</template>
345359

@@ -368,6 +382,7 @@ import { useAdminforth } from '@/adminforth';
368382
import Checkbox from '@/afcl/Checkbox.vue';
369383
import ListActionsThreeDots from '@/components/ListActionsThreeDots.vue';
370384
import CallActionWrapper from '@/components/CallActionWrapper.vue'
385+
import Select from '@/afcl/Select.vue';
371386
372387
const coreStore = useCoreStore();
373388
const { t } = useI18n();
@@ -378,6 +393,7 @@ const props = withDefaults(defineProps<{
378393
rows: any[] | null,
379394
totalRows: number,
380395
pageSize: number,
396+
pageSizeOptions?: { label: string; value: any }[];
381397
checkboxes: any[],
382398
sort: any[],
383399
noRoundings?: boolean,
@@ -405,6 +421,7 @@ const rowsToRender = computed(() => {
405421
// emits, update page
406422
const emits = defineEmits([
407423
'update:page',
424+
'update:pageSize',
408425
'update:sort',
409426
'update:checkboxes',
410427
'update:records'
@@ -414,6 +431,16 @@ const emits = defineEmits([
414431
const checkboxesInternal: Ref<any[]> = ref([]);
415432
const pageInput = ref('1');
416433
const page = ref(1);
434+
435+
const pageSizeInternal = ref(props.pageSize);
436+
437+
const pageSizeOptionsComputed = computed(() => {
438+
if (!props.pageSizeOptions || props.pageSizeOptions.length === 0) {
439+
return undefined;
440+
}
441+
return props.pageSizeOptions;
442+
});
443+
417444
const sort: Ref<Array<{field: string, direction: string}>> = ref([]);
418445
419446
const showListActionsThreeDots = computed(() => {
@@ -465,6 +492,14 @@ watch(() => props.page, (newPage) => {
465492
page.value = newPage;
466493
});
467494
495+
watch(() => props.pageSize, (newPageSize) => {
496+
pageSizeInternal.value = newPageSize;
497+
});
498+
499+
watch(pageSizeInternal, (newPageSize) => {
500+
emits('update:pageSize', newPageSize);
501+
});
502+
468503
const rowRefs = useTemplateRef<HTMLElement[]>('rowRefs');
469504
const headerRefs = useTemplateRef<HTMLElement[]>('headerRefs');
470505
const rowHeights = ref<number[]>([]);

adminforth/spa/src/views/ListView.vue

Lines changed: 35 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,8 @@
171171
@update:sort="sort = $event"
172172
@update:checkboxes="checkboxes = $event"
173173
@update:records="getListInner"
174+
:pageSizeOptions="PAGE_SIZE_OPTIONS"
175+
@update:pageSize="pageSize = $event"
174176
:sort="sort"
175177
:pageSize="pageSize"
176178
:totalRows="totalRows"
@@ -261,8 +263,19 @@ const customActionLoadingStates = ref<{[key: string]: boolean}>({});
261263
const DEFAULT_PAGE_SIZE = 10;
262264
263265
264-
const pageSize = computed(() => coreStore.resource?.options?.listPageSize || DEFAULT_PAGE_SIZE);
265-
const isVirtualScrollEnabled = computed(() => coreStore.resource?.options?.listVirtualScrollEnabled || false);
266+
const PAGE_SIZE_OPTIONS = computed(() => {
267+
const array = coreStore.resource?.options?.listPageSizeOptions;
268+
269+
if (!array || array.length === 0) return undefined;
270+
271+
return array.map(size => ({ label: size.toString(), value: size }));
272+
});
273+
274+
const pageSize = ref(DEFAULT_PAGE_SIZE);
275+
276+
const isVirtualScrollEnabled = computed(() =>
277+
coreStore.resource?.options?.listVirtualScrollEnabled || false
278+
);
266279
const listBufferSize = computed(() => coreStore.resource?.options?.listBufferSize || 30);
267280
268281
const isPageLoaded = ref(false);
@@ -426,7 +439,16 @@ async function init() {
426439
}
427440
// page init should be also in same tick
428441
if (route.query.page) {
429-
page.value = parseInt(route.query.page as string);
442+
page.value = parseInt(route.query.page as string);
443+
}
444+
if (route.query.pageSize) {
445+
const parsedPageSize = parseInt(route.query.pageSize as string);
446+
// Перевіряємо наявність опцій перед використанням .includes
447+
if (PAGE_SIZE_OPTIONS.value && PAGE_SIZE_OPTIONS.value.some(o => o.value === parsedPageSize)) {
448+
pageSize.value = parsedPageSize;
449+
}
450+
} else if (coreStore.resource?.options?.listPageSize) {
451+
pageSize.value = coreStore.resource.options.listPageSize;
430452
}
431453
432454
// getList(); - Not needed here, watch will trigger it
@@ -446,7 +468,7 @@ async function init() {
446468
}
447469
}
448470
449-
watch([page, sort, () => filtersStore.filters], async () => {
471+
watch([page, pageSize, sort, () => filtersStore.filters], async () => {
450472
// console.log('🔄️ page/sort/filter change fired, page:', page.value);
451473
await getListInner();
452474
}, { deep: true });
@@ -513,6 +535,15 @@ watch([page], async () => {
513535
setQuery({ page: page.value });
514536
});
515537
538+
watch(pageSize, async () => {
539+
page.value = 1;
540+
541+
setQuery({
542+
page: 1,
543+
pageSize: pageSize.value,
544+
});
545+
});
546+
516547
watch([sort], async () => {
517548
if (!sort.value.length) {
518549
setQuery({ sort: undefined });

adminforth/types/Common.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -472,6 +472,7 @@ export interface AdminForthResourceInputCommon {
472472
* Page size for list view
473473
*/
474474
listPageSize?: number,
475+
listPageSizeOptions?: number[],
475476

476477
/**
477478
* Whether to use virtual scroll in list view.

0 commit comments

Comments
 (0)