0
votes

I am trying to add a sum row to a v-data-table component as well as maintain sorting on the component. I have tried two approaches and both aren't optimal solutions.

Method 1) After the table has been mounted and the data has been fetched, push another row into the table with the sum of the data.

Something like this:

let total = 0
this.data.forEach(d => {
  total += d.someValue
})

this.data.push({
  value: total
})

This has the desired result on the table and you can use conditional class binding to bold the last row. The problem with this method is when sorting, the sum row moves like any other row. This is not optimal. The styling is perfect and exactly what I want it to be, but the sorting messes everything up.

Method 2) Using another v-data-table component with one row (the sum row) and adding it to the v-slot:footer in the parent table.

There are several issues with this method. The headers must be present and be exactly the same (apart from sorting) as the parent table. Otherwise, the spacing of the sum row is wrong (i.e. it's not directly underneath the column it's summing).

Since the headers, are present, there is a noticeable gap in between the footer and the rest of the table. Using display: none; on the footer table header messes up the column spacing as well. I believe Vuetify determines the width of the column by the width of the column header. The way to hide it seems to be using opacity: 0; This removes the headers, but leaves a blank space.

I tried adjusting the margins to bring the table closer to it's parent table, but that causes a new issue. Since the header of footer table is still there, it overlaps the last row of the table and makes the bottom row unusable.

Here's what that approach looks like:

<v-data-table :items-per-page="-1" :headers="headers" :items="items">
  <template v-slot:footer>
    <v-data-table
      :headers="headers"
      hide-default-footer
      style="font-weight: bold;"
      :items="[sum]">
    </v-data-table>    
  </template>
</v-data-table>

Anyone have a proper way to add a summation row while preserving sorting?

1

1 Answers

7
votes

You would need to use the body.append or the body.prepend slot. This will allow you to pass in the headers of your table and create a custom row that will persist sorting, filtering and paginating.

<v-data-table :headers="headers" :items="items">

    <template v-slot:body.append="{headers}">
        <tr>
            <td v-for="(header,i) in headers" :key="i">

                <div v-if="header.value == 'field1'">
                    {{field1Total}}
                </div>

                <div v-if="header.value == 'field2'">
                    {{field2Total}}
                </div>

                <div v-else>
                    <!-- empty table cells for columns that don't need a sum -->
                </div>

            </td>
        </tr>
    </template>

</v-data-table>