What's black, blue, and PACKED full of QTable slots?
...
The video version of this blog post!
The ideal progression for customizing rows with Quasar's QTable
is this:
- No slots, only props
- The generic "cell" slot (
#body-cell
) -
Specific "cell" slots (
#body-cell-[name]
) -
Row slots (
#body
)
The further down the list, the more flexibility and control you wield!
The further up the list, the more ease and abstraction.
So keep that in mind! If slots aren't needed, don't use them. They're there to offer flexibility when the defaults and props aren't enough.
Make sense?
Sweet! With that in mind, we'll dive in to Quasar's slots...
Oh! And if you want to learn all 72 of Quasar's components through videos, checkout QuasarComponents.Com 😉
Setup
First, for all you git cloners out there, Here's the GitHub Repo!
...
We'll use a similar setup to past examples with a couple of additions:
First, install lodash-es
yarn add lodash-es
Why lodash-es? Because it allows us to import individual functions easily without bringing in the THE WHOLE OF LODASH which is a MASSIVE dependency!
ahem, anywho...
Here's the setup:
<script>
import { copyToClipboard } from 'quasar'
import { ref } from 'vue'
import { sumBy, meanBy } from 'lodash-es'
export default {
setup () {
const rows = ref([
{
id: 1,
name: 'Panda',
email: 'panda@chihuahua.com',
age: 6
},
{
id: 2,
name: 'Lily',
email: 'lily@chihuahua.com',
age: 5
}
])
const columns = ref([
{ label: 'name', field: 'name', name: 'name', align: 'left' },
{ label: 'email', field: 'email', name: 'email', align: 'left' },
{ label: 'age', field: 'age', name: 'age', align: 'center' }
])
return {
copyToClipboard,
rows,
columns,
sumBy,
meanBy
}
}
}
</script>
Quasar comes with a handy copy to clipboard utility function that we'll use in one of the examples.
We'll also use sumBy
and meanBy
to build a summary row, and an average row.
I've also used ref
for the columns. Usually, you shouldn't do this since columns are almost never reactive! I've done it here, because in one of the examples we'll make columns editable!
Okay, put on your snorkel and we'll dive in 🤿
Generic Cell Slots (#body-cell)
Want to make all cells "copyable" with the press of a button?
no problem! We can use the #body-cell
prop for that...
<q-table
:rows="rows"
:columns="columns"
row-key="id"
>
<template #body-cell="props">
<q-td
:props="props"
>
<q-btn
flat
color="primary"
:label="props.value"
@click="copyToClipboard(props.value)"
/>
</q-td>
</template>
</q-table>
This is an easy way to target every cell. Notice that we're passing props
to q-td
? This basically allows us to proxy "Quasar Table Cell Stuff" easily 👍
Also notice we have access to the cells value with props.value
!
But what if we want to target specific cells...
Specific Cell Slots (#body-cell-[name])
tack on "name" and you can target any cell you like within a row.
You'll likely end up using this a lot, it's very handy! It's particularly useful for a delete button cell at the end of a row.
In this example, we use it to simply alternate colors:
<q-table
:rows="rows"
:columns="columns"
row-key="id"
>
<template #body-cell-name="props">
<q-td
class="bg-blue-1"
:props="props"
>
{{ props.value }}
</q-td>
</template>
<template #body-cell-email="props">
<q-td
class="bg-blue-2"
:props="props"
>
{{ props.value }}
</q-td>
</template>
<template
#body-cell-age="props"
>
<q-td
class="bg-blue-1"
:props="props"
>
{{ props.value }}
</q-td>
</template>
</q-table>
The API for #body-cell-[name]
is almost identical to #body-cell
(Classic Quasar! amazingly consistent API 🎉)
Row Slots (#body) (editable cells)
Before looking at this example, I want you to notice two things:
-
props
is proxied toq-tr
ANDq-td
. Once again, this is important as it allows Quasar to take control over the cell for things like "hiding columns" and setting therow-key
- We use
dense
andborderless
onq-input
, otherwise it looks strange in a table cell!
<q-table
:rows="rows"
:columns="columns"
row-key="id"
>
<template #body="props">
<q-tr
:props="props"
>
<q-td
key="name"
:props="props"
>
<q-input
v-model="props.row.name"
borderless
dense
/>
</q-td>
<q-td
key="email"
:props="props"
>
<q-input
v-model="props.row.email"
borderless
dense
/>
</q-td>
<q-td
key="age"
:props="props"
>
<q-input
v-model="props.row.age"
borderless
dense
input-class="text-center"
/>
</q-td>
</q-tr>
</template>
</q-table>
Doesn't look like much does it?
But take a look at that code... we're using QInput
's in the cells... These cells are EDITABLE!!!
This is a common question in the community.
"How do we achieve editable cells with q-table?"
well that my friends ☝️☝️☝️, is how 😉
The rest of this blog post will be very example driven with less eplanation.
The aim is to make you aware of what's possible, so you can go to bed tonight dreaming of table possibilities! 💤💭😶🌫️ (I have no idea what that second emoji is. Found it on emojifinder.com when searching for "dream")
SO!
Ready for this?
Sweet! Let's go nuts!!!
Header Cell Slots
Pretty much the same concept as body-cell
slots
<q-table
:rows="rows"
:columns="columns"
row-key="id"
>
<template #header-cell="props">
<q-th
style="font-size: 1.4em;"
class="text-primary"
:props="props"
>
{{ props.col.label }}
</q-th>
</template>
</q-table>
Specific Header Cell Slot
<q-table
:rows="rows"
:columns="columns"
row-key="id"
>
<template #header-cell-email="props">
<q-th :props="props">
<q-icon
size="sm"
name="email"
class="q-mr-sm"
color="grey-7"
/>{{ props.col.label }}
</q-th>
</template>
</q-table>
Header Row Slot
In this example, we make the header cells editable! Cool stuff 😎
<q-table
:rows="rows"
:columns="columns"
row-key="id"
>
<template #header="props">
<q-tr>
<q-th
key="name"
:props="props"
>
<q-input
v-model="columns[0].label"
dense
borderless
input-class="text-bold"
/>
</q-th>
<q-th
key="email"
:props="props"
>
<q-input
v-model="columns[1].label"
dense
borderless
input-class="text-bold"
/>
</q-th>
<q-th
key="age"
:props="props"
>
<q-input
v-model="columns[2].label"
dense
borderless
input-class="text-bold text-center"
/>
</q-th>
</q-tr>
</template>
</q-table>
Bottom And Top Row Slot
Great for aggregations and averages! This is where we use those lodash functions...
<q-table
:rows="rows"
:columns="columns"
row-key="id"
>
<template #top-row>
<q-tr class="bg-blue-1">
<q-td class="text-bold">
Average:
</q-td>
<q-td />
<q-td class="text-center">
{{ meanBy(rows, 'age') }}
</q-td>
</q-tr>
</template>
<template #bottom-row>
<q-tr class="bg-green-1">
<q-td class="text-bold">
Total:
</q-td>
<q-td />
<q-td class="text-center">
{{ sumBy(rows, 'age') }}
</q-td>
</q-tr>
</template>
</q-table>
Top Slot (above the actual table)
Perfect for things like filters and a search input
<q-table
:rows="rows"
:columns="columns"
row-key="id"
>
<template #top>
<div
class="text-bold"
style="font-size: 1.3em;"
>
Cute Pups
</div>
<q-input
class="q-ml-md"
dense
outlined
placeholder="Search"
>
<template #prepend>
<q-icon name="search" />
</template>
</q-input>
</template>
</q-table>
Bottom Slot (below the actual table)
Of course, we have total control over the bottom slot!
<q-table
:rows="rows"
:columns="columns"
row-key="id"
>
<template #bottom>
<span>
dogs from <a href="https://poochypoochypooch.com">poochypoochypooch.com</a>
</span>
</template>
</q-table>
Top Left and Top Right Slot
I like using #top-left
and #top-right
more than #top
. I almost always want something on either side, so it feels nicer than just using #top
...
<q-table
:rows="rows"
:columns="columns"
row-key="id"
>
<template #top-left>
<div
class="text-bold"
style="font-size: 1.3em;"
>
Cute Pups
</div>
</template>
<template #top-right>
<q-input
class="q-ml-md"
dense
outlined
placeholder="Search"
>
<template #prepend>
<q-icon name="search" />
</template>
</q-input>
</template>
</q-table>
No Data Slot
Of course, we can completely overwrite the message for no-data...
<q-table
:rows="[]"
:columns="columns"
row-key="id"
>
<template #no-data>
<div>Hmmm, I can't find any dang data!</div>
</template>
</q-table>
And That's It!
🎉🍾🎊🤗
Now, a question...
Can I Share My Story With You?
If you enjoyed this post half as much as I enjoyed making it for you, we'll be best friends!
And if you'd like to hear some of my story, head on over to QuasarComponents.Com.
I'll share the journey that lead to my love of Quasar, and tell you about the Massive component series I'm currently working on 🙃
So Click Here, and I'll see you on the other side!
...
Thanks for reading and remember,
There is nothing you can't build...
Top comments (3)
Awesome post!
Although the quasar docs are really nice, they are lacking an example of editable cells.
Starting with your code I raised an issue for an editable table in the quasar docs.
dev.to/quasar/quasar-s-qtable-the-...
Could you have a look at this post please? I have trouble with body slot.
Many thank for this lesson.
Is there a way to have the bottom slot and "free" pagination?