Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -319,6 +319,35 @@ export default {
]
```

### List Page Size Options
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.
```typescript title="./resources/apartments.ts"
export default {
resourceId: 'aparts',
options: {
...
listPageSize: 10,
//diff-add
listPageSizeOptions: [10, 20, 50],
}
}
]
```

#### How it works
- listPageSize defines the default number of records per page when the list is opened.
- listPageSizeOptions defines the available page size options shown to the user.

For example: listPageSizeOptions: [10, 20, 50] will allow switching between 10 / 20 / 50 records per page.

#### UI behavior
Page size switching is implemented via a select dropdown (select input) in the table pagination controls.
- User opens the select
- Chooses a value (e.g. 20)
- Table reloads with the new page size
> ☝️Notes
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.

### Virtual scroll

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.
Expand Down
44 changes: 44 additions & 0 deletions adminforth/spa/src/components/ResourceListTable.vue
Original file line number Diff line number Diff line change
Expand Up @@ -340,6 +340,20 @@
</span>
</template>
</span>
<div v-if="totalRows > 0 && pageSizeOptionsComputed?.length"
class="flex items-center gap-2 ml-auto" >
<span class="text-sm text-lightListTablePaginationHelpText dark:text-darkListTablePaginationHelpText">
{{ $t('Rows per page') }}
</span>
<Select v-model="pageSizeInternal"
:options="pageSizeOptionsComputed"
:searchDisabled="true"
class="text-sm w-[68px]"
classesForInput="h-[34px] min-h-0 py-1 pl-2 pr-6 text-sm rounded-md cursor-pointer af-button-shadow
bg-lightDropdownButtonsBackground text-lightDropdownButtonsText border-lightDropdownButtonsBorder
dark:bg-darkDropdownButtonsBackground dark:text-darkDropdownButtonsText dark:border-darkDropdownButtonsBorder"
/>
</div>
</div>
</template>

Expand Down Expand Up @@ -368,6 +382,7 @@ import { useAdminforth } from '@/adminforth';
import Checkbox from '@/afcl/Checkbox.vue';
import ListActionsThreeDots from '@/components/ListActionsThreeDots.vue';
import CallActionWrapper from '@/components/CallActionWrapper.vue'
import Select from '@/afcl/Select.vue';

const coreStore = useCoreStore();
const { t } = useI18n();
Expand All @@ -378,6 +393,7 @@ const props = withDefaults(defineProps<{
rows: any[] | null,
totalRows: number,
pageSize: number,
pageSizeOptions?: { label: string; value: any }[] | number[] | null;
checkboxes: any[],
sort: any[],
noRoundings?: boolean,
Expand Down Expand Up @@ -405,6 +421,7 @@ const rowsToRender = computed(() => {
// emits, update page
const emits = defineEmits([
'update:page',
'update:pageSize',
'update:sort',
'update:checkboxes',
'update:records'
Expand All @@ -414,6 +431,25 @@ const emits = defineEmits([
const checkboxesInternal: Ref<any[]> = ref([]);
const pageInput = ref('1');
const page = ref(1);

const pageSizeInternal = ref(props.pageSize);

const pageSizeOptionsComputed = computed(() => {
if (!props.pageSizeOptions || props.pageSizeOptions.length === 0) {
return null;
}

const firstItem = props.pageSizeOptions[0];
if (typeof firstItem === 'object' && firstItem !== null) {
return props.pageSizeOptions as { label: string; value: any }[];
}

return (props.pageSizeOptions as number[]).map(size => ({
label: size.toString(),
value: size
}));
});

const sort: Ref<Array<{field: string, direction: string}>> = ref([]);

const showListActionsThreeDots = computed(() => {
Expand Down Expand Up @@ -465,6 +501,14 @@ watch(() => props.page, (newPage) => {
page.value = newPage;
});

watch(() => props.pageSize, (newPageSize) => {
pageSizeInternal.value = newPageSize;
});

watch(pageSizeInternal, (newPageSize) => {
emits('update:pageSize', newPageSize);
});

const rowRefs = useTemplateRef<HTMLElement[]>('rowRefs');
const headerRefs = useTemplateRef<HTMLElement[]>('headerRefs');
const rowHeights = ref<number[]>([]);
Expand Down
39 changes: 35 additions & 4 deletions adminforth/spa/src/views/ListView.vue
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,8 @@
@update:sort="sort = $event"
@update:checkboxes="checkboxes = $event"
@update:records="getListInner"
:pageSizeOptions="PAGE_SIZE_OPTIONS"
@update:pageSize="pageSize = $event"
:sort="sort"
:pageSize="pageSize"
:totalRows="totalRows"
Expand Down Expand Up @@ -261,8 +263,19 @@ const customActionLoadingStates = ref<{[key: string]: boolean}>({});
const DEFAULT_PAGE_SIZE = 10;


const pageSize = computed(() => coreStore.resource?.options?.listPageSize || DEFAULT_PAGE_SIZE);
const isVirtualScrollEnabled = computed(() => coreStore.resource?.options?.listVirtualScrollEnabled || false);
const PAGE_SIZE_OPTIONS = computed(() => {
const array = coreStore.resource?.options?.listPageSizeOptions;

if (!array || array.length === 0) return undefined;

return array.map(size => ({ label: size.toString(), value: size }));
});

const pageSize = ref(DEFAULT_PAGE_SIZE);
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

const pageSize = computed(() => coreStore.resource?.options?.listPageSize || DEFAULT_PAGE_SIZE);

Why you changed this?

Are you sure old one is working?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The original computed property was read-only, which caused problems because we needed to update pageSize


const isVirtualScrollEnabled = computed(() =>
coreStore.resource?.options?.listVirtualScrollEnabled || false
);
const listBufferSize = computed(() => coreStore.resource?.options?.listBufferSize || 30);

const isPageLoaded = ref(false);
Expand Down Expand Up @@ -426,7 +439,16 @@ async function init() {
}
// page init should be also in same tick
if (route.query.page) {
page.value = parseInt(route.query.page as string);
page.value = parseInt(route.query.page as string);
}
if (route.query.pageSize) {
const parsedPageSize = parseInt(route.query.pageSize as string);
// Перевіряємо наявність опцій перед використанням .includes
if (PAGE_SIZE_OPTIONS.value && PAGE_SIZE_OPTIONS.value.some(o => o.value === parsedPageSize)) {
pageSize.value = parsedPageSize;
}
} else if (coreStore.resource?.options?.listPageSize) {
pageSize.value = coreStore.resource.options.listPageSize;
}

// getList(); - Not needed here, watch will trigger it
Expand All @@ -446,7 +468,7 @@ async function init() {
}
}

watch([page, sort, () => filtersStore.filters], async () => {
watch([page, pageSize, sort, () => filtersStore.filters], async () => {
// console.log('🔄️ page/sort/filter change fired, page:', page.value);
await getListInner();
}, { deep: true });
Expand Down Expand Up @@ -513,6 +535,15 @@ watch([page], async () => {
setQuery({ page: page.value });
});

watch(pageSize, async () => {
page.value = 1;

setQuery({
page: 1,
pageSize: pageSize.value,
});
});

watch([sort], async () => {
if (!sort.value.length) {
setQuery({ sort: undefined });
Expand Down
1 change: 1 addition & 0 deletions adminforth/types/Common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -472,6 +472,7 @@ export interface AdminForthResourceInputCommon {
* Page size for list view
*/
listPageSize?: number,
listPageSizeOptions?: number[],

/**
* Whether to use virtual scroll in list view.
Expand Down