Please see this pretty Example by Dave Fontz on CodePen on how to archive Date Table Inline Filter and to be able to customize how to display headers and tableData rows of a vuetify v-data-table.
This worked like acharm for me with vuetify version below 2.
However since upgrading to vuetify version 2 the
<template slot="headers" slot-scope="props">
and
<template slot="items" slot-scope="props">
inside
<v-data-table>
seem to be ignored.
Anyone any suggestion on how to migrate Daves solution to be compatible with vuetify version 2?
Any Help or Hint is much appreciated!
Complete Code by Dave also below.
HTML:
<div id="app">
<v-app id="inspire">
<v-data-table
v-model="selected"
:headers="headers"
:items="filteredDesserts"
:pagination.sync="pagination"
select-all
item-key="name"
class="elevation-1"
>
<template slot="headers" slot-scope="props">
<tr>
<th>
<v-checkbox
:input-value="props.all"
:indeterminate="props.indeterminate"
primary
hide-details
@click.native="toggleAll"
></v-checkbox>
</th>
<th
v-for="header in props.headers"
:key="header.text"
:class="['column sortable', pagination.descending ? 'desc' : 'asc', header.value === pagination.sortBy ? 'active' : '']"
@click="changeSort(header.value)"
>
<v-icon small>arrow_upward</v-icon>
{{ header.text }}
</th>
</tr>
<tr class="grey lighten-3">
<th>
<v-icon>filter_list</v-icon>
</th>
<th
v-for="header in props.headers"
:key="header.text"
>
<div v-if="filters.hasOwnProperty(header.value)">
<v-select flat hide-details small multiple clearable :items="columnValueList(header.value)" v-model="filters[header.value]">
</v-select>
</div>
</th>
</tr>
</template>
<template slot="items" slot-scope="props">
<tr :active="props.selected" @click="props.selected = !props.selected">
<td>
<v-checkbox
:input-value="props.selected"
primary
hide-details
></v-checkbox>
</td>
<td>{{ props.item.name }}</td>
<td class="text-xs-right">{{ props.item.calories }}</td>
<td class="text-xs-right">{{ props.item.fat }}</td>
<td class="text-xs-right">{{ props.item.carbs }}</td>
<td class="text-xs-right">{{ props.item.protein }}</td>
<td class="text-xs-right">{{ props.item.iron }}</td>
</tr>
</template>
</v-data-table>
</v-app>
</div>
JS:
new Vue({
el: '#app',
data: () => ({
pagination: {
sortBy: 'name'
},
selected: [],
headers: [
{
text: 'Dessert (100g serving)',
align: 'left',
value: 'name'
},
{ text: 'Calories', value: 'calories' },
{ text: 'Fat (g)', value: 'fat' },
{ text: 'Carbs (g)', value: 'carbs' },
{ text: 'Protein (g)', value: 'protein' },
{ text: 'Iron (%)', value: 'iron' }
],
filters: {
fat: [],
carbs: [],
iron: [],
},
desserts: [
{
value: false,
name: 'Frozen Yogurt',
calories: 159,
fat: 6.0,
carbs: 24,
protein: 4.0,
iron: '1%'
},
{
value: false,
name: 'Ice cream sandwich',
calories: 237,
fat: 9.0,
carbs: 37,
protein: 4.3,
iron: '1%'
},
{
value: false,
name: 'Eclair',
calories: 262,
fat: 16.0,
carbs: 23,
protein: 6.0,
iron: '7%'
},
{
value: false,
name: 'Cupcake',
calories: 305,
fat: 3.7,
carbs: 67,
protein: 4.3,
iron: '8%'
},
{
value: false,
name: 'Gingerbread',
calories: 356,
fat: 16.0,
carbs: 49,
protein: 3.9,
iron: '16%'
},
{
value: false,
name: 'Jelly bean',
calories: 375,
fat: 0.0,
carbs: 94,
protein: 0.0,
iron: '0%'
},
{
value: false,
name: 'Lollipop',
calories: 392,
fat: 0.2,
carbs: 98,
protein: 0,
iron: '2%'
},
{
value: false,
name: 'Honeycomb',
calories: 408,
fat: 3.2,
carbs: 87,
protein: 6.5,
iron: '45%'
},
{
value: false,
name: 'Donut',
calories: 452,
fat: 25.0,
carbs: 51,
protein: 4.9,
iron: '22%'
},
{
value: false,
name: 'KitKat',
calories: 518,
fat: 26.0,
carbs: 65,
protein: 7,
iron: '6%'
}
]
}),
computed: {
filteredDesserts() {
return this.desserts.filter(d => {
return Object.keys(this.filters).every(f => {
return this.filters[f].length < 1 || this.filters[f].includes(d[f])
})
})
}
},
methods: {
toggleAll () {
if (this.selected.length) this.selected = []
else this.selected = this.desserts.slice()
},
changeSort (column) {
if (this.pagination.sortBy === column) {
this.pagination.descending = !this.pagination.descending
} else {
this.pagination.sortBy = column
this.pagination.descending = false
}
},
columnValueList(val) {
return this.desserts.map(d => d[val])
}
}
})
See it in Action on CodePen
I made a pen that filters columns, it's not exactly what you asked for, but it might give you an idea. It uses custom filtering from vuetify 2 documentation
HTML:
<div id="app">
<v-app id="inspire">
<template>
<div>
<v-data-table
dense
:headers="headers"
:items="desserts"
item-key="name"
class="elevation-1"
:search="search"
>
<template v-slot:body.prepend>
<tr>
<td>
<v-text-field v-model="search" type="text" label="Dessert name"></v-text-field>
</td>
<td>
<v-text-field v-model="calories" type="number" label="Less than"></v-text-field>
</td>
<td>
<v-text-field v-model="fat" type="number" label="Less than"></v-text-field>
</td>
<td>
<v-text-field v-model="carbs" type="number" label="Less than"></v-text-field>
</td>
</tr>
</template>
</v-data-table>
</div>
</template>
</v-app>
</div>
and JS:
new Vue({
el: '#app',
vuetify: new Vuetify(),
data () {
return {
search: '',
name: '',
calories: '',
fat:'',
carbs:'',
desserts: [
{
name: 'Frozen Yogurt',
calories: 159,
fat: 6.0,
carbs: 24
},
{
name: 'Ice cream sandwich',
calories: 237,
fat: 9.0,
carbs: 37,
},
{
name: 'Eclair',
calories: 262,
fat: 16.0,
carbs: 23,
},
{
name: 'Cupcake',
calories: 305,
fat: 3.7,
carbs: 67,
},
{
name: 'Gingerbread',
calories: 356,
fat: 16.0,
carbs: 49,
},
{
name: 'Jelly bean',
calories: 375,
fat: 0.0,
carbs: 94,
},
{
name: 'Lollipop',
calories: 392,
fat: 0.2,
carbs: 98,
},
{
name: 'Honeycomb',
calories: 408,
fat: 3.2,
carbs: 87,
},
{
name: 'Donut',
calories: 452,
fat: 25.0,
carbs: 51,
},
{
name: 'KitKat',
calories: 518,
fat: 26.0,
carbs: 65,
},
],
}
},
computed: {
headers () {
return [
{
text: 'Dessert (100g serving)',
align: 'left',
sortable: false,
value: 'name',
filter: value => {
if (!this.name) return true
return value < value
}
},
{
text: 'Calories',
value: 'calories',
filter: value => {
if (!this.calories) return true
return value < parseInt(this.calories)
}
},
{ text: 'Fat (g)', value: 'fat',filter: value => {
if (!this.fat) return true
return value < parseInt(this.fat)
}, },
{ text: 'Carbs (g)', value: 'carbs',
filter: value => {
if (!this.carbs) return true
return value < parseInt(this.carbs)
}
}
]
}
}
})
I made a pen vuetify 2 data table column sort filter
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With