I'm new to Vuetify and am struggling to add the default filter and sort capabilities back into a table with a custom header.
The HTML:
<v-data-table
:headers="headers"
:items="items"
item-key="client"
:footer-props="footerProps"
:search="search"
class="text-body-1"
>
<template #header="{ props }">
<thead class="v-data-table-header">
<tr>
<th
v-for="header in props.headers"
:key="header.value"
:class="{
'grey white--text text-body-1': true,
'sortable': header.sortable,
'filter': header.filterable,
}"
scope="col"
>
{{ header.text }}
</th>
</tr>
</thead>
</template>
The data structure for the headers I am working off of looks as follow:
headers: [
new TableHeader('Number', 'index', false, false),
new TableHeader('EMP Code', 'empCode', false, false),
]
and the TableHeader:
export default function (header, prop, sortable = true, filterable = false, align = 'start') {
this.text = header
this.value = prop
this.sortable = sortable
this.filterable = filterable
this.align = align
}
With all this, the table header looks exactly the way it is supposed to but I can no longer click on the header and sort it.
Does anyone know how to add the default filter and sort back or maybe just a different way to style the header that keeps the default header functionalities with custom styling. Nothing changes on the header except for the style.
(I've seen lots of questions similar to this one but none of them really answer it in a way I can replicate :')
I'm expecting my header to have custom styling with the default functionalities (sort, filter, etc.) but I am getting a custom look with no default functionalities (sort, filter, etc.)
The #header
slot receives an object on
as slot prop, which contains callbacks:
on: {
sort: (value: string) => void,
group: (value: string) => void,
toggle-select-all: (value: boolean) => void
}
Pass header.value
to the on.sort
function to trigger sorting:
<template #header="{ props, on }">
<tr>
<th
v-for="header in props.headers"
...
@click="on.sort(header.value)"
>
...
It will go trough the same sort order cycle as on regular headers (off -> asc -> desc -> off).
Here it is in a snippet:
new Vue({
el: '#app',
vuetify: new Vuetify(),
template: `
<v-app>
<v-main>
<v-container>
<v-data-table
:items="items"
:headers="headers"
>
<template #header="{props, on: {sort}}">
<tr>
<th
v-for="header in props.headers"
:key="header.value"
@click="sort(header.value)"
>
Le {{header.value}} <span
v-if="props.options.sortBy[0] === header.value"
>{{ props.options.sortDesc[0] ? 'desc' : 'asc'}}
</span>
</th>
</tr>
</template>
</v-data-table>
</v-container>
</v-main>
</v-app>
`,
data(){
return {
headers: [{text: 'Number', value: 'number'}, {text: 'Letter', value: 'letter'}],
items: Array.from({length: 5}, (_,i) => ({number: i+1, letter: String.fromCharCode(90-i)})),
}
},
methods: {
log(...x){console.log(...x)}
}
})
<link href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/@mdi/font@6.x/css/materialdesignicons.min.css" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/vuetify@2.x/dist/vuetify.min.css" rel="stylesheet">
<div id="app"></div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.x/dist/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vuetify@2.x/dist/vuetify.js"></script>