From 150d3e9af7a1c3b1926d2a67598d94521942d120 Mon Sep 17 00:00:00 2001 From: Konstantinos Paparas Date: Mon, 18 Sep 2023 15:34:51 +0200 Subject: [PATCH] fix(DataTable): add internal pagination support Co-authored-by: Luki Centuri --- example/src/views/DataTableView.vue | 7 ++- src/components/tables/DataTable.vue | 68 +++++++++++++++++++++-------- 2 files changed, 55 insertions(+), 20 deletions(-) diff --git a/example/src/views/DataTableView.vue b/example/src/views/DataTableView.vue index 98f1b1c..eb6059c 100644 --- a/example/src/views/DataTableView.vue +++ b/example/src/views/DataTableView.vue @@ -253,7 +253,12 @@ const emptyTables = ref< const datatables = ref<{ title: string; table: DataTableProps }[]>([ { title: 'With Column definitions', - table: { rowAttr: 'id', rows: [], cols: fixedColumns }, + table: { + rowAttr: 'id', + rows: [], + cols: fixedColumns, + hideDefaultFooter: true, + }, }, { title: 'No Column definitions', diff --git a/src/components/tables/DataTable.vue b/src/components/tables/DataTable.vue index f4f7f5f..f2959f5 100644 --- a/src/components/tables/DataTable.vue +++ b/src/components/tables/DataTable.vue @@ -14,6 +14,7 @@ export interface TableColumn { direction?: 'asc' | 'desc'; align?: 'start' | 'center' | 'end'; class?: string; + cellClass?: string; [key: string]: any; } @@ -44,6 +45,11 @@ export interface Props { * model for insternal searching */ search?: string; + /** + * model for items per page + * will be used if the `pagination` model isn't specified + */ + itemsPerPage?: number; /** * model for paginating data * @example v-model:pagination="{ total: 10, limit: 5, page: 1 }" @@ -101,6 +107,10 @@ export interface Props { empty?: { label?: string; description?: string }; rounded?: 'sm' | 'md' | 'lg'; + /** + * should hide the footer + */ + hideDefaultFooter?: boolean; } defineOptions({ @@ -111,6 +121,7 @@ const props = withDefaults(defineProps(), { value: undefined, search: '', cols: undefined, + itemsPerPage: 10, pagination: undefined, columnAttr: 'label', sort: undefined, @@ -119,13 +130,14 @@ const props = withDefaults(defineProps(), { sortModifiers: undefined, empty: () => ({ label: 'No item found' }), rounded: 'md', + hideDefaultFooter: false, }); const emit = defineEmits<{ (e: 'input', value?: string[]): void; - (e: 'update:pagination', value?: TablePaginationData): void; + (e: 'update:pagination', value: TablePaginationData): void; (e: 'update:sort', value?: SortColumn | SortColumn[]): void; - (e: 'update:options', value?: TableOptions): void; + (e: 'update:options', value: TableOptions): void; }>(); const { @@ -134,6 +146,7 @@ const { value, columnAttr, rowAttr, + itemsPerPage, pagination, paginationModifiers, search, @@ -167,16 +180,26 @@ const selectedData = computed({ }, }); +const internalPaginationState: Ref = ref(); + +watchImmediate(pagination, (pagination) => { + set(internalPaginationState, pagination); +}); + /** * Pagination is different for search * since search is only used for internal filtering * we return the length of search results as total */ -const paginationData = computed({ +const paginationData: Ref = computed({ get() { - const paginated = get(pagination); - if (!paginated || !get(search)) { - return paginated; + const paginated = get(internalPaginationState); + if (!paginated) { + return { + total: get(searchData).length, + limit: get(itemsPerPage), + page: 1, + }; } return { @@ -186,7 +209,8 @@ const paginationData = computed({ limits: paginated.limits, }; }, - set(value) { + set(value: TablePaginationData) { + set(internalPaginationState, value); emit('update:pagination', value); emit('update:options', { pagination: value, @@ -296,19 +320,20 @@ const sorted = computed(() => { const sort = (by: SortColumn) => { data.sort((a, b) => { - if (!by.column) { + const column = by.column; + if (!column) { return 0; } if (by.direction === 'desc') { - return `${b[by.column]}`.localeCompare( - `${a[by.column]}`, + return `${b[column]}`.localeCompare( + `${a[column]}`, undefined, sortOptions, ); } - return `${a[by.column]}`.localeCompare( - `${b[by.column]}`, + return `${a[column]}`.localeCompare( + `${b[column]}`, undefined, sortOptions, ); @@ -325,15 +350,16 @@ const sorted = computed(() => { }); /** - * comprises of search, sorted and paginated data + * comprises search, sorted and paginated data */ const filtered = computed(() => { const result = get(sorted); - const paginated = get(pagination); + const paginated = get(paginationData); + const limit = paginated.limit; if (paginated && !get(paginationModifiers)?.external) { - const start = (paginated.page - 1) * paginated.limit; - const end = start + paginated.limit; + const start = (paginated.page - 1) * limit; + const end = start + limit; return result.slice(start, end); } @@ -546,7 +572,7 @@ watch(search, () => {