DEV Community

Cover image for Quasar's QTable: The ULTIMATE Component (2/6) - Expandable Rows and Selectable Rows
Luke for Quasar

Posted on • Updated on

Quasar's QTable: The ULTIMATE Component (2/6) - Expandable Rows and Selectable Rows

Prefer video? I got ya covered!

I use selectable rows, and expandable rows all the time! I'll give you a real world example.

We record "spraying events" for paddocks, and sometimes a paddock will be sprayed many times! Our app groups individual sprays by paddock, and also gives a "total amount sprayed" in the parent row!

Paddock Sprays With QTable

Now look at what happens when we click on one of the rows...

Paddock Sprays With QTable Expanded

The farmers LOVE IT! And guess what...

It was surprisingly easy to build with Quasar's QTable! I'll show you how 😊

Also, notice the Totals row at the bottom? Also a piece of cake with Quasar! (more on summary rows in a future blog post)

Now before we dive in, take a look at QuasarComponents.Com for some action packed, heart POUNDING, nail biting, high intensity videos on all 72 of Quasar's components!

click here and I'll see you on the other side 😁

A Little Setup

Let's do some basic setup so things run smoothly!



<script>
import { ref } from 'vue'

export default {
  setup () {
    const selected = ref()

    const rows = [
      {
        id: 1,
        name: 'Panda',
        email: 'panda@chihuahua.com',
        age: 6
      },
      {
        id: 2,
        name: 'Lily',
        email: 'lily@chihuahua.com',
        age: 5
      }
    ]

    const columns = [
      { label: 'expand', name: 'expand', field: 'expand' },
      { label: 'id', field: 'id', name: 'id' },
      { label: 'name', field: 'name', name: 'name' },
      { label: 'email', field: 'email', name: 'email' },
      { label: 'age', field: 'age', name: 'age' }
    ]

    return {
      rows,
      columns,
      selected
    }
  }
}
</script>


Enter fullscreen mode Exit fullscreen mode

and here's the github repo

Expandable Rows

Expandable rows are made possible with the #body slot. I'll here's how it's done 😎



<q-table
  :rows="rows"
  :columns="columns"
  row-key="id"
>
  <template #body="props">
    <q-tr :props="props">
      <!-- Expand cell/button -->
      <q-td
        key="expand"
        name="expand"
        :props="props"
        auto-width
      >
        <!--
          The important part here is
          @click="props.expand = !props.expand"
        -->
        <q-btn
          flat
          round
          :icon="props.expand ? 'remove' : 'add'"
          @click="props.expand = !props.expand"
        />
      </q-td>
      <!--
        Notice that we the "key" matches the columns "name" property
        Notice that we "proxy" the props from #body="props" to our q-td
      -->
      <q-td
        key="id"
        :props="props"
      >
        {{ props.row.id }}
      </q-td>
      <q-td
        key="name"
        :props="props"
      >
        {{ props.row.name }}
      </q-td>
      <q-td
        key="email"
        :props="props"
      >
        {{ props.row.email }}
      </q-td>
      <q-td
        key="age"
        :props="props"
      >
        {{ props.row.age }}
      </q-td>
    </q-tr>
    <!-- We show the row if "props.expand" is toggled to true! -->
    <q-tr
      v-show="props.expand"
      :props="props"
    >
      <q-td colspan="100%">
        <div class="text-left">
          Expanded
        </div>
      </q-td>
    </q-tr>
  </template>
</q-table>


Enter fullscreen mode Exit fullscreen mode

all closed
Basic QTable Expandable Row Example Closed
one row expanded
Basic QTable Expandable Row Example Opened

A few things to note here:

First: The #body slot allows us to tap into individual rows

Second: we use Quasar's q-tr and q-td components to build the row. This gives us INSANE control!

Third: We use the scope (#body="props") and pass it to every q-td and q-tr. This is important! It means our q-tr's and q-td's get all the styling they need for things like dense and visible-columns (more on those later)

Fouth: We can toggle/track if a row is expanded with props.expanded

Read those four points back and forth until they make sense! Understand them, and you'll have IMMENSE power over Quasar's QTable!

Also notice that in the expanded row, we use colspan="100%" to basically say "take up all the space in this row". Helpful for things like "create" buttons that insert new rows.

AND, auto-width which "Tries to shrink column width size; Useful for columns with a checkbox/radio/toggle"

Individual Cells For Each Row

To be thorough, here's an example where the expanded row has cells, lining up with cells on the parent row...



<!-- Expandable Row (cells) -->
<q-table
  :rows="rows"
  :columns="columns"
  row-key="id"
>
  <template #body="props">
    <!-- PARENT ROW -->
    <q-tr :props="props">
      <!-- Expand cell/button -->
      <q-td
        key="expand"
        name="expand"
        :props="props"
        auto-width
      >
        <q-btn
          flat
          round
          :icon="props.expand ? 'remove' : 'add'"
          @click="props.expand = !props.expand"
        />
      </q-td>
      <q-td
        key="id"
        :props="props"
      >
        {{ props.row.id }}
      </q-td>
      <q-td
        key="name"
        :props="props"
      >
        {{ props.row.name }}
      </q-td>
      <q-td
        key="email"
        :props="props"
      >
        {{ props.row.email }}
      </q-td>
      <q-td
        key="age"
        :props="props"
      >
        {{ props.row.age }}
      </q-td>
    </q-tr>
    <!-- CHILD ROW -->
    <q-tr
      v-show="props.expand"
      :props="props"
    >
      <!--
        Might want to leave the first cell blank, as it is
        simply space for the "expand" column
      -->
      <q-td
        key="expand"
        :props="props"
      />
      <q-td :props="props">
        summary
      </q-td>
      <q-td
        key="id"
        :props="props"
      >
        summary
      </q-td>
      <q-td
        key="name"
        :props="props"
      >
        summary
      </q-td>
      <q-td
        key="email"
        :props="props"
      >
        summary
      </q-td>
      <q-td
        key="age"
        :props="props"
      >
        summary
      </q-td>
    </q-tr>
  </template>
</q-table>


Enter fullscreen mode Exit fullscreen mode

Expandable Rows With Cells In The Child Row

those places that say "summary"... You can put whatever you like in those cells!

BIG TIP: use props.row to access the current row 🚣

HA! Emoji joke 😆

It's also worth noting that you can have as many "child" rows as you like!

And THAT my friend, is expandable rows. now let's move on to making rows selectable.

Selectable Rows. A Gift From Quasar 🎁

This truly is a gift! I've implemented a "selectable rows" feature myself in the past and you know what?

It SUCKS!

Quasar makes it easier than blowing out a two year old's birthday candles 🎂 (which you shouldn't do, that's not cool)...

Check it!



<q-table
  v-model:selected="selected"
  selection="single"
  :rows="rows"
  row-key="id"
/>


Enter fullscreen mode Exit fullscreen mode

QTable Basic Selection

Yes! It really is that flippen easy 😱😱😱

Do I even need to explain this code!?

The one thing to note, is row-key is used to uniquely identify the selected data, so you'll need it!

HOT TIP: use the pre tag to display this data nicely when testing...



<pre>{{ selected }}</pre>


Enter fullscreen mode Exit fullscreen mode

That's what all the cool kids are doing (or so I'm told)

"But Luke! I want to use a TOGGLE, not a checkbox

Oh!? Do ya now!?

No worries my inquisitive friend! Rollup your sleeves and try this!



<q-table
  v-model:selected="selected"
  selection="multiple"
  :rows="rows"
  row-key="id"
>
  <template #header-selection="scope">
    <q-toggle v-model="scope.selected" />
  </template>

  <template #body-selection="scope">
    <q-toggle v-model="scope.selected" />
  </template>
</q-table>


Enter fullscreen mode Exit fullscreen mode

Customizing Quasar QTable Selected With Slots

(did you catch my cheeky rollup joke?)

Note that scope.selected is a simple function that toggles the selection for you. Easy right?

Are you starting to see how Quasar's API makes building components bliss? I LOVE it ❤️

multiple select

You can enable multiple select by changing selection="single" to selection="multiple" 🍪

"Luke! This Is SO COOL! I Want MORE"

Oh nice, I love your enthusiasm!

If you want to learn more about this stuff, head on over to QuasarComponents.Com

In that series, we will...

All proceeds are donated directly to the Quasar Dev team!

Check it out here


Thanks for reading 🤓. Tomorrow we'll cover Loading State, Pagination, and Sorting (You're gonna LOVE Pagination).

Bye for now! And please for the love of code remember,

There is nothing you can't build...

Top comments (1)

Collapse
 
cdecinkoknight profile image
cdecinkoKnight

I've added the ability to hide show rows which works great. Except, if you have a row expanded and go to the next page in the results... then go back to that previous page, all using the table navigation, you see the expanded row icon but the row is not expanded. If I click and click again then the row displays. How can I reset all the expanded rows when moving from page to page in the table?