I’m building a vue.js component that wraps around a vuetify data table. I’ve added props so I can make it fetch data from different sources – and that data will have different columns.
It’s supposed to be used like this:
<FancyTable endpoint="/api/buildings" />
<FancyTable endpoint="/api/persons" />
Here’s a simplified version of the component:
<template>
<v-data-table-server
:items="items"
:items-length="totalItems"
@update:options="fetchData"
item-key="id"
>
<template #[`item.address_type`]="{ item }">
<building-icon :icon="item.address_type"></building-icon>
</template>
</v-data-table-server>
</template>
<script>
import BuildingIcon from '@/components/BuildingIcon.vue'
import { VDataTableServer } from 'vuetify/components'
export default {
name: 'FancyTable',
components: { BuildingIcon, VDataTableServer },
data: () => ({
totalItems: 0,
items: [],
options: {}
}),
props: {
endpoint: {
type: String,
required: true
}
},
watch: {
options: {
handler() {
this.fetchData()
},
deep: true
}
},
methods: {
fetchData: function () {
const { sortBy, sortDesc, page, itemsPerPage } = this.options
// here, we would fetch data from an actual backend, using the sort and filter options
console.log('fetching / faking results from: ', this.endpoint)
let fake_backend_results = []
let fake_backend_count = 0
if (this.endpoint === '/api/buildings')
{
fake_backend_results = [
{ id: 0, address_type: 'building', address: 'Berliner Tor 13' },
{ id: 1, address_type: 'building', address: 'Berliner Tor 15' },
{ id: 2, address_type: 'cabinet', address: 'Berliner Tor 17' },
{ id: 3, address_type: 'cabinet', address: 'Berliner Tor 19' },
{ id: 4, address_type: 'booth', address: 'Berliner Tor 21' }
]
fake_backend_count = 27
} else if (this.endpoint === '/api/persons') {
fake_backend_results = [
{ id: 35, first_name: 'Jane', last_name: 'Doe' },
{ id: 36, first_name: 'John', last_name: 'Doe' }
]
fake_backend_count = 2
}
this.items = fake_backend_results
this.totalItems = Number(fake_backend_count)
}
}
}
</script>
Now, this works fine as it is, but it is not as generic as I like it to be: The <template>
block that customizes the .address_type
column is the part that I’d like to insert that from the outside, like this:
<FancyTable endpoint="/api/buildings">
<template #[`item.address_type`]="{ item }">
<building-icon :icon="item.address_type"></building-icon>
</template>
</FancyTable>
How would I pass down dynamic slots like these to the VDataTableServer
? I assume that a solution would revolve around a v-for
with a <template><slot /></template>
construct, but I cannot figure out how to do that correctly.