quasarframework / quasar

Quasar Framework - Build high-performance VueJS user interfaces in record time
https://quasar.dev
MIT License
25.75k stars 3.5k forks source link

QTable - slot for `expand` #8350

Open Razi91 opened 3 years ago

Razi91 commented 3 years ago

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:

Razi91 commented 3 years ago

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

AlexDaniel commented 2 years ago

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

mark134340 commented 2 years ago

This is required for nested tables!

Razi91 commented 2 years ago

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

Razi91 commented 2 years ago

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 commented 2 years ago

bump, any suggestions?

goldelehr commented 2 years ago

Can't wait to have this feature in Quasar V2

Razi91 commented 2 years ago

I created PR for that, but there is no response

Razi91 commented 2 years ago

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

meshwara commented 2 years ago

Any update for this please ?

jsormaz commented 1 year ago

Is this implemented in any way yet?

LoliWithPick commented 1 year ago

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

Razi91 commented 1 year ago

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

maximang commented 10 months ago

Any update on that?

Qualzz commented 9 months ago

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.

akshymalvia commented 8 months ago

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>
Miosss commented 6 months ago

+1

CDT commented 1 week ago

Need this feature, please have a look. This thread was created at 2021 and still open, I wonder why no maintainer is paying attention.