Vuetifyのv-data-tableに行クリックで行展開する方法

# はじめに
Vuetifyでデータテーブルを実装することがあり、行クリックで行展開したいなと思ってました。
そこで実装してみた内容をメモしておこうと思います。

# 行展開の実装方法
行展開ではshow-expandを指定すると、行展開アイコンが表示されて展開できるようになります。

```vue
<template>
  <v-data-table :headers="headers" :items="items" show-expand>
    <template v-slot:expanded-item="{ headers, item }">
      <td :colspan="headers.length">
        <div style="padding: 5px">
          <h4>趣味</h4>
          <ul>
            <li v-for="hobby of item.hobbies" :key="hobby">
              {{ hobby }}
            </li>
          </ul>
        </div>
      </td>
    </template>
  </v-data-table>
</template>

<script>
export default {
  data() {
    return {
      headers: [
        { text: "ID", value: "id" },
        { text: "氏名", value: "name" },
        { text: "誕生日", value: "birthday" },
        { text: "年齢", value: "age" },
      ],
      items: [
        {
          id: 1,
          name: "山田太郎",
          birthday: "1990/1/1",
          age: 31,
          hobbies: ["サッカー", "野球"],
        },
        {
          id: 2,
          name: "佐藤花子",
          birthday: "1991/1/1",
          age: 30,
          hobbies: ["茶道", "テニス", "スキー"],
        },
        {
          id: 3,
          name: "田中一郎",
          birthday: "1992/1/1",
          age: 29,
          hobbies: ["ピアノ", "柔道", "ダンス", "ボルダリング"],
        },
      ],
    };
  },
};
</script>
```

![test.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1206533/48a8818c-948f-2d6b-4f76-a58707f23fb5.png)

# 行クリックによる行展開の実装方法
v-data-table APIのイベントを確認してみると、「click:row」というものがあります。
引数を2つ渡すことができ、1つ目の引数は「クリックされた行データ(item)」、2つ目の引数は「itemスロットによる関連データ」を取ることができるみたいです。
以下はitemスロットのデータみたいなのですが、「expand」と「isExpanded」を利用することで行クリックの開閉ができそうです。

```javascript
any, {
  expand: (value: boolean) => void,
  headers: DataTableHeader[],
  isExpanded: boolean,
  isMobile: boolean,
  isSelected: boolean,
  item: any,
  select: (value: boolean) => void
}
```

>Emits when a table row is clicked. This event provides 2 arguments: the first is the item data that was clicked and the second is the other related data provided by the item slot. NOTE: will not emit when table rows are defined through a slot such as item or body.

https://vuetifyjs.com/ja/api/v-data-table/#events


```vue
<template>
  <v-data-table
    :headers="headers"
    :items="items"
    show-expand
    @click:row="(item, slot) => slot.expand(!slot.isExpanded)"
  >
    <template v-slot:expanded-item="{ headers, item }">
      <td :colspan="headers.length">
        <div style="padding: 5px">
          <h4>趣味</h4>
          <ul>
            <li v-for="hobby of item.hobbies" :key="hobby">
              {{ hobby }}
            </li>
          </ul>
        </div>
      </td>
    </template>
  </v-data-table>
</template>

<script>
export default {
  data() {
    return {
      headers: [
        { text: "ID", value: "id" },
        { text: "氏名", value: "name" },
        { text: "誕生日", value: "birthday" },
        { text: "年齢", value: "age" },
      ],
      items: [
        {
          id: 1,
          name: "山田太郎",
          birthday: "1990/1/1",
          age: 31,
          hobbies: ["サッカー", "野球"],
        },
        {
          id: 2,
          name: "佐藤花子",
          birthday: "1991/1/1",
          age: 30,
          hobbies: ["茶道", "テニス", "スキー"],
        },
        {
          id: 3,
          name: "田中一郎",
          birthday: "1992/1/1",
          age: 29,
          hobbies: ["ピアノ", "柔道", "ダンス", "ボルダリング"],
        },
      ],
    };
  },
};
</script>
```

![Videotogif.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1206533/8559fcd4-c3d6-cb20-d693-b7713ad05c08.gif)




これで行クリックによる行展開ができるようになりました。
「!slot.isExpanded」 で行展開しているかどうかをbooleanで判別し、展開されてないなら「true」を返します。
「slot.expand(!slot.isExpanded)」で上記のようにtrueなら行展開されるようなロジックです。