quasar icon indicating copy to clipboard operation
quasar copied to clipboard

QTable - slot for `expand`

Open Razi91 opened this issue 4 years ago • 20 comments

Is your feature request related to a problem? Please describe. There is expand prop in QTable for rows. Docs show it's usage: https://quasar.dev/vue-components/table#Expanding-rows

Describe the solution you'd like Current implementation requires to define all cells manually. I think there should be separate slot for the expanded row

Additional context At the end of __getTBodyTR I've added:

      const expandScope = this.$scopedSlots['expand']
      if (expandScope !== void 0 && this.isRowExpanded(key)) {
        const { key, ...trData } = data
        const td = h('q-td', {
          attrs: {
            colspan: '100%'
          }
        }, [expandScope(this.__getBodyScope({
          key: key + '-expanded',
          row,
          pageIndex,
          __trClass: selected ? 'selected' : ''
        }))]
        )
        return [h('tr', data, child), h('tr', [td])]
      }
      return h('tr', data, child)

It allows me to use in template:

      <template v-slot:body-selection="props">
        <q-checkbox v-model="props.expand"/>
      </template>
      <template v-slot:expand="props">
        <div class="text-left">
          This is expand slot for row above: {{ props.row.name }}.
          <q-input v-model="props.row.input" />
        </div>
      </template>

Currently I've cheated with body-selection slot, but hey, it works! New slot has the same props as body, so migration should be easy. Unresolved problems:

  • Should developer manually include <tr><td colspan="100%"></td></tr> tags? Or just let Quasar do it?
  • Should all props be available?
  • Should expand switch be defined and rendered, if slot is provided by default?

Razi91 avatar Jan 20 '21 23:01 Razi91

Ok, some progress expand

      <template v-slot:expand="props">
        <div class="text-left">
          This is expand slot for row above: {{ props.row.name }}
        </div>
      </template>

just adding this slot adds toggle at the beginning (actuale second, if there is selection). Of course adding slot body-expand allows to modify that cell.

This is working example, just waiting for suggestions, then I can make PR

Razi91 avatar Jan 21 '21 00:01 Razi91

Uh, any progress? Coming from vuetify and really missing this feature.

AlexDaniel avatar Dec 07 '21 18:12 AlexDaniel

This is required for nested tables!

mark134340 avatar Jan 01 '22 10:01 mark134340

I had it done for Quasar V1, since we are migrating to V2, I'll do it for V2, this time properly

Razi91 avatar Jan 03 '22 14:01 Razi91

Okay, now I need it for V2, so I did it for V2. I just need some tips, about design and code style. First, the example data-table-part8-expanded (https://github.com/quasarframework/quasar/blob/dev/ui/dev/src/pages/components/data-table-part8-expanded.vue) In my branch it looks like this:

    <q-table
      :rows="data"
      :columns="columns"
      row-key="name"
      title="Inner expanded"
    >
      <template v-slot:body-cell-desc="props">
        <q-td :props="props">
          <div class="row items-center">
            <q-toggle v-model="props.expand" checked-icon="add" unchecked-icon="remove" />
            <div>%%% {{ props.row.name }} %%%</div>
          </div>
        </q-td>
      </template>
      <template v-slot:body-cell-iron="props">
        <q-td :props="props">
          <q-badge square color="amber">
            {{ props.row.iron }}
          </q-badge>
        </q-td>
      </template>
      <template v-slot:row-expand="props">
        <q-tr v-show="props.expand" :props="props">
          <q-td colspan="100%">
            <div class="text-left">
              This is expand slot for row above: {{ props.row.name }}.
              <q-input v-model="props.row.input" />
            </div>
          </q-td>
        </q-tr>
      </template>
    </q-table>

Props are the same as for v-slot:body.

About QTable.js, in getTBodyTR:

      const expandedSlot = slots[ 'row-expand' ]
      if (expandedSlot !== void 0) {
        const expanded = expandedSlot(getBodyScope({
          key,
          row,
          pageIndex,
          __trClass: selected ? 'selected' : ''
        }))
        return [
          h('tr', data, child),
          expanded
        ]
      }
      return h('tr', data, child)

I'm not sure if it's correct way to do it and follows the code style guideline. I've created PR so you can see the difference.

Backward compatibility is achieved, if you don't implement row-expand slot explicitly, nothing will change.

I still think if I should automatically add a column with switch or not. I think user should do it manually, since it could be on row click, be on some button etc.

Razi91 avatar Mar 31 '22 20:03 Razi91

bump, any suggestions?

Razi91 avatar Apr 15 '22 11:04 Razi91

Can't wait to have this feature in Quasar V2

goldelehr avatar May 13 '22 16:05 goldelehr

I created PR for that, but there is no response

Razi91 avatar May 13 '22 22:05 Razi91

Bump, is there any chance to merge it soon? Or maybe some changes need to be done?

Razi91 avatar Jun 09 '22 09:06 Razi91

Any update for this please ?

meshwara avatar Jul 13 '22 00:07 meshwara

Is this implemented in any way yet?

jsormaz avatar Feb 03 '23 19:02 jsormaz

Are there any new updates on this? I need it badly now!!!

LoliWithPick avatar Jun 11 '23 09:06 LoliWithPick

I've migrated to the latest version, fixed virtual scroll and waiting for accepting

Razi91 avatar Aug 25 '23 07:08 Razi91

Any update on that?

maximang avatar Oct 31 '23 07:10 maximang

what is happening with this PR ? At least if it's not accepted we should know why. This is a very important feature as the current implementation is worse than this PR.

Qualzz avatar Dec 15 '23 13:12 Qualzz

I've created a base component with a custom conditional slot for an expandable row.

Here's the snippet for reference.

<template>
  <q-table
    ref="component"
    :columns="visibleColumns"
    :table-header-class="tableHeaderClass"
    :virtual-scroll-sticky-size-start="48"
    card-class="full-height bg-neutral-20"
    table-class="full-height"
    flat
    virtual-scroll
  >
// pass through slots
    <template
      v-for="(slot, index) of Object.keys($slots)"
      :key="index"
      #[slot]="slotProps"
    >
      <slot v-if="slotProps" v-bind="slotProps" :name="slot"></slot>
      <slot v-else :name="slot"></slot>
    </template>

// custom header if the table has expandable rows
    <template v-if="expandableRows" #header="headerProps">
      <q-tr :class="tableHeaderClass" :props="headerProps">
        <q-th class="expand-toggle" auto-width />

        <q-th
          v-for="col in headerProps.cols"
          :key="col.name"
          :props="headerProps"
          class="ellipsis"
        >
          {{ col.label }}
        </q-th>
      </q-tr>
    </template>

// custom slots for default and expanded row
    <template v-if="expandableRows" #body="bodyProps">
      <q-tr :key="`m_${bodyProps.rowIndex}`" :props="bodyProps">
        <q-td v-if="expandableRows" class="expand-toggle">
          <ExpandToggleCell
            :dense="$attrs.dense !== undefined"
            :expanded="isExpanded(bodyProps.rowIndex)"
            @click="toggleExpandedRow(bodyProps.rowIndex)"
          />
        </q-td>
        <slot name="row" v-bind="bodyProps">
          <span>Row</span>
        </slot>
      </q-tr>
      <q-tr
        v-if="isExpanded(bodyProps.rowIndex)"
        :key="`m_${bodyProps.rowIndex}`"
        :props="bodyProps"
        class="q-virtual-scroll--with-prev"
      >
        <slot name="expanded-row" v-bind="bodyProps">
          <span>Expanded Row</span>
        </slot>
      </q-tr>
    </template>

    <template #no-data="{ message }">
      <div class="text-center full-width">
        <span class="text-sm">{{ message }}</span>
      </div>
    </template>
  </q-table>
</template>

akshymalvia avatar Jan 02 '24 10:01 akshymalvia

+1

Miosss avatar Mar 20 '24 13:03 Miosss