Skip to content
This repository has been archived by the owner on Sep 30, 2024. It is now read-only.

Commit

Permalink
fix(DataTable): add internal pagination support
Browse files Browse the repository at this point in the history
Co-authored-by: Luki Centuri <lukicenturi@gmail.com>
  • Loading branch information
kelsos and lukicenturi committed Sep 18, 2023
1 parent b4bb7c7 commit 150d3e9
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 20 deletions.
7 changes: 6 additions & 1 deletion example/src/views/DataTableView.vue
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down
68 changes: 49 additions & 19 deletions src/components/tables/DataTable.vue
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ export interface TableColumn {
direction?: 'asc' | 'desc';
align?: 'start' | 'center' | 'end';
class?: string;
cellClass?: string;
[key: string]: any;
}
Expand Down Expand Up @@ -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 }"
Expand Down Expand Up @@ -101,6 +107,10 @@ export interface Props {
empty?: { label?: string; description?: string };
rounded?: 'sm' | 'md' | 'lg';
/**
* should hide the footer
*/
hideDefaultFooter?: boolean;
}
defineOptions({
Expand All @@ -111,6 +121,7 @@ const props = withDefaults(defineProps<Props>(), {
value: undefined,
search: '',
cols: undefined,
itemsPerPage: 10,
pagination: undefined,
columnAttr: 'label',
sort: undefined,
Expand All @@ -119,13 +130,14 @@ const props = withDefaults(defineProps<Props>(), {
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 {
Expand All @@ -134,6 +146,7 @@ const {
value,
columnAttr,
rowAttr,
itemsPerPage,
pagination,
paginationModifiers,
search,
Expand Down Expand Up @@ -167,16 +180,26 @@ const selectedData = computed({
},
});
const internalPaginationState: Ref<TablePaginationData | undefined> = 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<TablePaginationData> = 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 {
Expand All @@ -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,
Expand Down Expand Up @@ -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,
);
Expand All @@ -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);
}
Expand Down Expand Up @@ -546,7 +572,7 @@ watch(search, () => {
<template #append>
<Icon
v-if="column.align != 'end'"
v-if="column.align !== 'end'"
:class="css.sort__icon"
name="arrow-down-line"
size="18"
Expand Down Expand Up @@ -606,7 +632,11 @@ watch(search, () => {
<td
v-for="(column, subIndex) in columns"
:key="subIndex"
:class="[css.td, css[`align__${column.align ?? 'start'}`]]"
:class="[
css.td,
column.cellClass,
css[`align__${column.align ?? 'start'}`],
]"
>
<slot
:name="`item.${column.key}`"
Expand Down Expand Up @@ -661,7 +691,7 @@ watch(search, () => {
</table>
</div>
<TablePagination
v-if="paginationData"
v-if="paginationData && !hideDefaultFooter"
v-model="paginationData"
:loading="loading"
:dense="dense"
Expand Down

0 comments on commit 150d3e9

Please sign in to comment.