DEV Community

Cover image for Quasar's QTable: The ULTIMATE Component (4/6) - ALL The Slots!
Luke for Quasar

Posted on

Quasar's QTable: The ULTIMATE Component (4/6) - ALL The Slots!

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:

  1. No slots, only props
  2. The generic "cell" slot (#body-cell)
  3. Specific "cell" slots (#body-cell-[name])
  4. 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


Enter fullscreen mode Exit fullscreen mode

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>


Enter fullscreen mode Exit fullscreen mode

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>


Enter fullscreen mode Exit fullscreen mode

Customizing Quasar Table Cells With Slots

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>


Enter fullscreen mode Exit fullscreen mode

Customizing Specific Quasar Table Cells With Slots

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:

  1. props is proxied to q-tr AND q-td. Once again, this is important as it allows Quasar to take control over the cell for things like "hiding columns" and setting the row-key
  2. We use dense and borderless on q-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>


Enter fullscreen mode Exit fullscreen mode

Quasar QTable With Editable Cells

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>


Enter fullscreen mode Exit fullscreen mode

Quasar QTable Header Cell Slots

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>


Enter fullscreen mode Exit fullscreen mode

Quasar QTable Specific Header Cell Slot

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>


Enter fullscreen mode Exit fullscreen mode

Quasar QTable Header Row Slot

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>


Enter fullscreen mode Exit fullscreen mode

Quasar QTable Bottom And Top Row Slot

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>


Enter fullscreen mode Exit fullscreen mode

Quasar QTable Customizing the Top With A Search Input

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>


Enter fullscreen mode Exit fullscreen mode

Quasar QTable Customizing The Bottom

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>


Enter fullscreen mode Exit fullscreen mode

Quasar QTable Top Left and Top Right Slot

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>


Enter fullscreen mode Exit fullscreen mode

Quasar QTable No Data Slot Example

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)

Collapse
 
hhaensel profile image
hhaensel

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-...

  <q-table :columns="columns" v-model="table" :rows="rows" row-key="__id">
      <template v-slot:body-cell="props">
          <q-td>
              <q-input label="" v-model="props.row[props.col.name]"
                input-style="font-size: 0.81rem; padding-top: 2px"
                input-class="bg-red-1 q-px-sm"
                 dense borderless></q-input>
          </q-td>
      </template>
  </q-table>
Enter fullscreen mode Exit fullscreen mode

Image description

Collapse
 
jaaf profile image
jaaf

Could you have a look at this post please? I have trouble with body slot.
Many thank for this lesson.

Collapse
 
dru profile image
Asdrubal

Is there a way to have the bottom slot and "free" pagination?