Quasar's QTable: The ULTIMATE Component (2/6) - Expandable Rows and Selectable Rows
Tags: quasar, vue, javascript, webdev
Published: 2021-08-17 11:43:48

Prefer video? I got ya covered!

{% youtube f5Vn0MU5u6w %}

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](https://i.imgur.com/qtLZRyr.png)

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

![Paddock Sprays With QTable Expanded](https://i.imgur.com/QxtoB4B.png)

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](https://quasarcomponents.com) for some **action packed**, heart **POUNDING**, nail **biting**, high **intensity** videos on [all 72 of Quasar's components!](https://quasarcomponents.com)

[click here](https://quasarcomponents.com) and I'll see you on the other side 😁

## A Little Setup
Let's do some basic setup so things run smoothly!

```javascript
<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>
```

[and here's the github repo](https://github.com/ldiebold/q-table-blog)

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

```vue
<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>
```
**all closed**
![Basic QTable Expandable Row Example Closed](https://i.imgur.com/fQ06tvw.png)
**one row expanded**
![Basic QTable Expandable Row Example Opened](https://i.imgur.com/jWkLe6s.png)


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

```vue
<!-- 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>
```

![Expandable Rows With Cells In The Child Row](https://i.imgur.com/RYqt0vU.png)

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!

```vue
<q-table
  v-model:selected="selected"
  selection="single"
  :rows="rows"
  row-key="id"
/>
```
![QTable Basic Selection](https://i.imgur.com/LNh0Mpz.png)

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

```vue
<pre>{{ selected }}</pre>
```
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!

```vue
<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>
```

![Customizing Quasar QTable Selected With Slots](https://i.imgur.com/DvUyFCu.png)

(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](https://quasarcomponents.com)

In that series, we will...
- Cover [**all 72**](https://quasarcomponents.com) of Quasar's Components
- Build [**YouTube's UI**](https://quasarcomponents.com) with Quasar
- Build [a **Live Chat App**](https://quasarcomponents.com) with Laravel and Quasar
- Build a Quasar [**App Extension**](https://quasarcomponents.com)

All proceeds are donated directly to the Quasar Dev team!

[Check it out here](https://quasarcomponents.com)

-----

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