I have this function fetchItemData that fetches data from the DB and assigns it to itemsList
, which is bound to items
of v-data-table. The v-data-table shows the new data perfectly fine on other events, like a change in sort parameters or items-per-page. But when searchText changes (@input event on v-text-field), despite the data being returned perfectly fine and assigned to itemsList with no problems, it does not show up in the table at all and I get the no-data screen.
Even when I added a debug function printItems
that simply ran console.log(this.itemsList)
upon the table being clicked, it shows that the itemsList = a list of items matching the search query. They’re just not being shown.
I have a reduced version of my code here with extraneous things removed:
Template:
<template>
<v-card class="pa-4">
<v-data-table
v-model="selected"
v-model:sort-by="sortBy"
v-model:items-per-page="itemsPerPage"
v-model:page="pageNum"
:search="searchText"
:headers="headers"
:items="itemsList"
:loading="itemsLoading"
:pageText="allFetched ? '{0}-{1} of {2}' : '{0}-{1} of more'"
:last-icon="allFetched ? '$last' : ''"
@update:itemsPerPage="fetchItemData"
@update:sortBy="fetchItemData"
@update:page="fetchNextPage"
item-key="id">
<template v-slot:top>
<v-container fluid>
<v-row class="pb-2">
<v-text-field
v-model="searchText"
label="Search"
prepend-inner-icon="mdi-magnify"
bg-color="transparent"
variant="underlined"
density="compact"
single-line
hide-details
clearable
@input="fetchItemData" />
<v-btn
v-if="selected && selected.length"
@click="() => {}"
color="error"
size="small"
class="ml-4 float-right align-self-end">
Delete Selected
</v-btn>
</v-row>
</v-container>
</template>
<template v-slot:loading>
<v-skeleton-loader type="table-tbody" />
</template>
<template v-slot:no-data>
<div class="mt-6 text-subtitle-1">No data found</div>
<v-btn
class="mt-2 mb-6"
color="primary"
size="small"
variant="flat"
prepend-icon="mdi-refresh"
@click="fetchItemData"> // <- the problem
Retry
</v-btn>
</template>
templates for item rows etc...
</v-data-table>
</v-card>
</template>
Script:
import { items } from '@/services/items.js'
export default {
data: () => ({
itemsList: [],
itemsLoading: false,
itemsPerPage: 10,
pageNum: 1,
searchText: '',
selected: [],
sortBy: [{ key: 'updatedAt', order: 'desc' }],
allFetched: false
}),
methods: {
fetchItemData() {
var numToFetch = this.itemsPerPage + 1 //get one extra so next button remains active if there exist items past curr page
var searchParams = {
query: this.searchText
}
var pageParams = {
size: numToFetch,
sort: this.sortBy[0]
}
this.itemsLoading = true
items
.list(searchParams, pageParams)
.then((response) => {
if (response.data) {
this.itemsList = response.data?.items || []
} else {
this.itemsList = []
}
//if items received is less than num to fetch, we've reached end
if (response.data?.items && response.data.items.length < numToFetch)
this.allFetched = true
this.itemsLoading = false
return this.itemsList
})
.catch(() => {
this.itemsList = []
this.itemsLoading = false
})
},
fetchNextPage() {...}
computed: {
headers() {
return [
row headers...
]
}
},
created() {
this.fetchItemData()
},
name: 'ItemsTable'
}
Any help would be much appreciated: thank you!