[Vuetify]v-data-table のグループヘッダーをカスタマイズ

NuxtJSVuetifyv-data-table のレコードをグループ化したときにグループヘッダーをカスタマイズする方法をメモしておきます。

前提条件

  • vue : 2.6.14
  • nuxt : 2.15.8
  • vuetify : 2.6.1

こちらから今回のソースコードを確認できます。

グループ化

まずは、普通に v-data-table のグループ化をしてみます。

DataTableCustom.vue

template タグ部分

<template>
  <v-card>
    <v-card-title>データテーブルグループ化カスタマイズ</v-card-title>
    <v-data-table :items='items' :headers='headers' show-group-by group-by='group' />
  </v-card>
</template>

script タグ部分

export default {
  name: 'DataTableCustom',
  data() {
    return {
      items: [
        { id: '1', name: '牛乳', value: 10, group: 'グループ1' },
        { id: '2', name: 'チーズ', value: 20, group: 'グループ2' },
        { id: '3', name: 'ヨーグルト', value: 30, group: 'グループ3' },
        { id: '4', name: 'バター', value: 40, group: 'グループ3' },
        { id: '5', name: '練乳', value: 50, group: 'グループ3' },
        { id: '6', name: 'クリーム', value: 60, group: 'グループ2' },
        { id: '7', name: 'アイスクリーム', value: 70, group: 'グループ2' },
        { id: '8', name: '脱脂粉乳', value: 80, group: 'グループ1' },
        { id: '9', name: '乳酸菌飲料', value: 90, group: 'グループ1' },
        { id: '10', name: 'ホエイプロテイン', value: 100, group: 'グループ1' },
      ],
      headers: [
        { text: 'ID', value: 'id', groupable: false },
        { text: '名称', value: 'name', groupable: false },
        { text: '値', value: 'value', groupable: false },
        { text: 'グループ', value: 'group' },
      ]
    }
  },
}
    <v-data-table :items='items' :headers='headers' show-group-by group-by='group' />

items にデータレコード、 headers にテーブルヘッダーの情報を設定します。グループ化する場合は、 show-group-by prop を指定します。 group-by プロパティにグループ化するフィールド名を指定します。

Vuetify v-data-table 1

グループヘッダーをカスタマイズする

グループヘッダーをカスタマイズするには group.header slot を使用します。

template タグ部分

<template>
  <v-card>
    <v-card-title>データテーブルグループ化カスタマイズ</v-card-title>
    <v-data-table :items='items' :headers='headers' show-group-by group-by='group'>
      <template #[`group.header`]="{ group, items, headers, toggle, isOpen, remove }">
        <td>
          <v-btn @click="toggle" x-small icon :ref="group">
            <v-icon v-if="isOpen">mdi-minus</v-icon>
            <v-icon v-else>mdi-plus</v-icon>
          </v-btn>
          {{ group }}
          <v-btn @click='remove' x-small icon :ref='group'>
            <v-icon>mdi-close</v-icon>
          </v-btn>
        </td>
        <td>小計:{{ getTotal(items) }}</td>
        <td :colspan="headers.length-2"></td>
      </template>
    </v-data-table>
  </v-card>
</template>

script タグ部分

export default {
  name: 'DataTableCustom',
  data() {
    return {
      items: [
        { id: '1', name: '牛乳', value: 10, group: 'グループ1' },
        { id: '2', name: 'チーズ', value: 20, group: 'グループ2' },
        { id: '3', name: 'ヨーグルト', value: 30, group: 'グループ3' },
        { id: '4', name: 'バター', value: 40, group: 'グループ3' },
        { id: '5', name: '練乳', value: 50, group: 'グループ3' },
        { id: '6', name: 'クリーム', value: 60, group: 'グループ2' },
        { id: '7', name: 'アイスクリーム', value: 70, group: 'グループ2' },
        { id: '8', name: '脱脂粉乳', value: 80, group: 'グループ1' },
        { id: '9', name: '乳酸菌飲料', value: 90, group: 'グループ1' },
        { id: '10', name: 'ホエイプロテイン', value: 100, group: 'グループ1' },
      ],
      headers: [
        { text: 'ID', value: 'id', groupable: false },
        { text: '名称', value: 'name', groupable: false },
        { text: '値', value: 'value', groupable: false },
        { text: 'グループ', value: 'group' },
      ]
    }
  },
  methods: {
    getTotal(items) {
      let total = 0
      total = items.reduce((prev, current) => {
        return prev + current.value
      }, 0)
      return total
    }
  }
}

今回はグループごとの値の小計を計算してグループヘッダーに表示しています。

Vuetify v-data-table 2

グループの最後にサマリーレコードを追加することもできる

group.summary slot を使用するとグループ化されたレコードの最後にサマリーレコードを表示することもできます。

template タグ部分

<template>
  <v-card>
    <v-card-title>データテーブルグループ化カスタマイズ</v-card-title>
    <v-data-table :items='items' :headers='headers' show-group-by group-by='group'>
      <template #[`group.header`]="{ group, items, headers, toggle, isOpen, remove }">
        <td>
          <v-btn @click="toggle" x-small icon :ref="group">
            <v-icon v-if="isOpen">mdi-minus</v-icon>
            <v-icon v-else>mdi-plus</v-icon>
          </v-btn>
          {{ group }}
          <v-btn @click='remove' x-small icon :ref='group'>
            <v-icon>mdi-close</v-icon>
          </v-btn>
        </td>
        <td>小計:{{ getTotal(items) }}</td>
        <td :colspan="headers.length-2"></td>
      </template>
      <template #[`group.summary`]="{ items, headers }">
        <td>小計:{{ getTotal(items) }}</td>
        <td :colspan="headers.length-1"></td>
      </template>
    </v-data-table>
  </v-card>
</template>

script タグ部分

export default {
  name: 'DataTableCustom',
  data() {
    return {
      items: [
        { id: '1', name: '牛乳', value: 10, group: 'グループ1' },
        { id: '2', name: 'チーズ', value: 20, group: 'グループ2' },
        { id: '3', name: 'ヨーグルト', value: 30, group: 'グループ3' },
        { id: '4', name: 'バター', value: 40, group: 'グループ3' },
        { id: '5', name: '練乳', value: 50, group: 'グループ3' },
        { id: '6', name: 'クリーム', value: 60, group: 'グループ2' },
        { id: '7', name: 'アイスクリーム', value: 70, group: 'グループ2' },
        { id: '8', name: '脱脂粉乳', value: 80, group: 'グループ1' },
        { id: '9', name: '乳酸菌飲料', value: 90, group: 'グループ1' },
        { id: '10', name: 'ホエイプロテイン', value: 100, group: 'グループ1' },
      ],
      headers: [
        { text: 'ID', value: 'id', groupable: false },
        { text: '名称', value: 'name', groupable: false },
        { text: '値', value: 'value', groupable: false },
        { text: 'グループ', value: 'group' },
      ]
    }
  },
  methods: {
    getTotal(items) {
      let total = 0
      total = items.reduce((prev, current) => {
        return prev + current.value
      }, 0)
      return total
    }
  }
}

Vuetify v-data-table 3

最後に

レコードをグループ化した際に、グループの先頭に表示したいグループの情報、グループの末尾に表示したいグループの情報があるの思いますので、状況に応じて今回説明した slots を活用していきたいですね。

こちらから今回のソースコードを確認できます。

コメントする

メールアドレスが公開されることはありません。 が付いている欄は必須項目です