Reputation: 1
I have a global v-data-table-server element that is used throughout the service (other applications inherit it and substitute their values). In each application, it is determined which columns will be sorted, and by what value the sorting will be (example below).
Example of app registry:
export default {
components: {
TableWithPaginateAndSorting,
},
setup() {
const router = useRouter();
const headers = [
{ title: 'ID', key: 'id' },
{ title: 'Short_name', key: 'short_name' },
{ title: 'Email', key: 'email' },
{ title: 'Phone', key: 'phone_number', sortable: false },
{ title: 'Organizations count', key: 'org_count', sortKey: 'organizations_count' },
{ title: '', key: 'actions', sortable: false },
];
const table = ref(null);
const registerStore = useRegistersStore();
const handleClickShowDetail = (item = { id: null }) => {
router.push({
name: 'RegDepartmentsDetailPage',
params: { id: item.id },
});
};
const handleCloseModal = (needUpdate) => {
if (needUpdate) table.value.fetchAllItems();
};
'sortKey' is the value in the JSON response that the column is sorted by. The problem is that if there is a default sorting, then table sorts fine. But when a value with a custom sort key comes across, the table does not display or save the current sorting status. The sorting itself is working, but I can't change it anymore. (the table is sorted in ascending order and stored in this position, and i can't change that).
table
<slot name="prependTable"></slot>
<v-card elevation="0" class="custom-table-card">
<v-data-table-server
class="custom-table-onpage"
:headers="headers.map((i) => ({ ...i}))"
:items="items.results"
:loading="isLoading"
items-per-page-text="Items per page"
:items-per-page="paginate.page_size"
:items-length="items.count"
:hide-default-footer="true"
@click:row="(e, item) => $emit('clickRow', item.item.raw)"
:items-per-page-options="[
{ value: 5, title: '5' },
{ value: 10, title: '10' },
{ value: 15, title: '15' },
]"
:page="paginate.page"
:sort-by="sort"
@update:sortBy="handleSort"
@update:page="(e) => handlePaginate({ ...paginate, page: e })"
@update:itemsPerPage="
(e) => handlePaginate({ ...paginate, page_size: e })
"
>
<template v-slot:bottom></template>
<template
v-for="sName in cSlots"
v-slot:[getCSlotsName(sName)]="{ item }"
>
<slot :name="sName" :item="item.selectable"></slot>
</template>
<template v-slot:item.created_at="{ item }">
{{ dateFromIso(item.selectable.created_at) }}
</template>
<template v-slot:item.birthday="{ item }">
{{ dateFromIso(item.selectable.birthday, 'date') }}
</template>
<template v-slot:item.actions="{ item }">
<div class="d-flex">
<slot name="prependActions" :item="item.raw"></slot>
<v-tooltip text='Details'>
<template v-slot:activator="{ props }">
<v-btn
v-bind='props'
variant="text"
icon
@click="$emit('detail', item.raw)"
>
<img src="@/assets/icons/common/outlined/link.png" alt="link" />
</v-btn>
</template>
</v-tooltip>
<v-tooltip text='Delete'>
<template v-slot:activator="{ props }">
<v-btn
v-bind="props"
v-if="!withoutDel"
color="red"
icon="mdi-delete"
variant="text"
@click="() => handleClickRemoveItem(item.raw, 'remove')"
></v-btn>
</template>
</v-tooltip>
<slot name="appendActions" :item="item.raw"></slot>
</div>
</template>
</v-data-table-server>
<slot name="body"></slot>
</v-card>
<custom-pagination
is-hide-per-page
:per-page="paginate.page_size"
:page="paginate.page"
:count="items.count"
@update="handlePaginate"
/>
<confirm-modal
:is-show="isShowConfirmedRemove"
@action="handleConfirmClick"
/>
</template>
<style>
.custom-table-card
.v-table__wrapper
tbody.v-data-table__tbody
.v-data-table__tr
td:first-child {
border-left: none !important;
}
.custom-table-card
.v-table__wrapper
tbody.v-data-table__tbody
.v-data-table__tr
td {
border-right: none !important;
}
</style>
<script>
import FilterSidebar from '@/components/common/FilterSidebar.vue';
import ConfirmModal from '@/components/modals/common/ConfirmModal.vue';
import RadioTags from '@/components/common/RadioTags/RadioTags.vue';
import { dateFromIso } from '@/helpers';
import CustomPagination from '@/components/element/CustomPagination.vue';
export default {
name: 'TableWithPaginateAndSorting',
emits: ['addClick', 'detail', 'remove'],
components: { CustomPagination, ConfirmModal, RadioTags },
data: () => ({
isShowConfirmedRemove: false,
removedItem: null,
confirmedEventName: '',
}),
props: {
isLoading: {
type: Boolean,
default: false,
},
withoutDel: {
type: Boolean,
default: false,
},
headers: {
type: Array,
required: true,
},
items: {
type: Object,
required: true,
},
paginate: {
type: Object,
required: true,
},
sort: {
type: Array,
default: () => [{ key: 'id', order: 'asc' }],
},
cSlots: {
type: Array,
default: () => [],
},
filters: {
type: Array,
default: () => [],
},
tags: {
type: Object,
default: () => ({}),
},
showAddBtn: {
type: Boolean,
default: false,
},
hideFilters: {
type: Boolean,
default: false,
},
addQueryParamsForAllItems: {
type: Object,
required: false,
default: () => ({}),
},
// props from pinia
getAllItems: {
type: Function,
required: true,
},
changeSort: {
type: Function,
required: true,
},
changePagination: {
type: Function,
required: true,
},
changeFilters: {
type: Function,
required: true,
},
},
sort func
handleSort(e) {
const headers = this.headers;
console.log(e);
if (e.length !== 0) {
for (let i in headers) {
if (e[0].key === headers[i].key) {
e[0].title = e[0].order === 'asc' ?
`${headers[i].title} ascending` : `${headers[i].title} descending`;
if (headers[i].sortKey) {
e[0].key = headers[i].sortKey;
}
}
}
}
console.log(e);
this.changeSort(e);
this.fetchAllItems();
},
I realized that the problem is that there is no header in the table, which the table is trying to find with sortedKey. If you pass the usual key in such headers, everything is OK, the sorting status is displayed and changes, but the sorting itself starts to work incorrectly. I.e., with sortedKey, vuetify does not understand which column needs to be sorted and sorts the entire table at a time. Is there any way to fix this?
Upvotes: 0
Views: 89