vuetifyのテーブルが簡単高機能でオシャレ　使い方


vuetifyを使うと、オシャレで高機能なテーブルが簡単に使えたのでメモします。


この記事でやることは以下の3点です。
* テーブルの設定
* アイテムの削除
* axiosを使ってアイテムを設定する



:confetti_ball::confetti_ball::confetti_ball:*ここでお知らせです。*:confetti_ball::confetti_ball::confetti_ball:

こんなサイトで使ってます。
https://kintorenote.com/

これはaxiosでサーバーからデータを取得して、テーブルのデータとして使っています。

イメージです
<img width="581" alt="スクリーンショット 2019-12-01 14.37.02.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/201764/6cc06898-f5ca-a3d8-b962-16cfb0566c2b.png">


サーバーからデータを取得して、その内容をテーブルの要素(item)として表示するなんてこともできますので、便利です



## テーブルの設定を行う

公式サイトはこれです。
https://vuetifyjs.com/ja/components/data-tables


テーブルを使う準備をします。
テーブルに必要なのは、headersとitemsです。
どちらも、配列の中にオブジェクトを入れて定義します。やってみると単純なのでやっていきます。

```vue:main.vue
<template>
  <v-container>
    <v-row>
      <v-col cols="10">
        <v-data-table
          :headers="headers"
          :items="items"
        ></v-data-table>
      </v-col>
      </v-row>
  </v-container>
</template>
```

テーブルは v-data-tableにヘッダーとアイテムを指定すれば出来上がりです。


### ヘッダーを定義する

ヘッダーではヘッダーに表示する内容を定義するのですが、同時にヘッダーと紐付くitemsのkeyを定義して起きます。

今回はIDと名前と年齢というカラムを持つテーブルを作ります。

```vue:main.vue
<script>
export default {

  data(){
    return {
      headers: [
          { 
            text: 'ID', 
            value: 'id' 
          },
          {
            text: '名前',
            value: 'name',
          },
          { text: '年齢', 
            value: 'age' 
          },
        ],
    }
  },
  
}
</script>
```

配列の中にオブジェクトを突っ込みます。
オブジェクトはtextとvalueを持っていて、textがヘッダーに表示される名称で、valueは、後に用意するitemのkeyになります。
まぁ書いてみるとわかりやすいです。

### itemを用意する

itemはテーブルの中身です。
今回必要な情報はidとnameとageになります。
テーブルのitemも、headerと同じで配列の中にオブジェクトを入れて作ります。

```vue:main.vue
      items:[
        { 
          id : 1 , 
          name : "高田健志" , 
          age : 33 
        },
        { 
          id : 2 , 
          name : "横山緑" , 
          age: 42
        },
        { 
          id : 3 , 
          name : "山田太郎" , 
          age: 10
        },
      ]
```

dataに追加します。
これで準備完了です。

以下のように表示されています

<img width="759" alt="スクリーンショット 2019-11-25 23.41.49.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/201764/3018279b-7f19-5b99-b69c-063b2cb0670d.png">

ちなみに、ソート機能がついています。
<img width="759" alt="スクリーンショット 2019-11-25 23.43.37.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/201764/f2e77230-03e9-c921-4842-000a5ebd4bfe.png">
年齢でソートしたものです。


## 削除行を追加して削除機能を付ける

これだけでも超絶クールなテーブルなんですが
削除機能もつけます。
公式をみるとサンプルがあるので、ごっそりあれしてみます。

まずはヘッダーに削除を追加します。

```vue:main.vue
     headers: [
          { 
            text: 'ID', 
            value: 'id' 
          },
          {
            text: '名前',
            value: 'name',
          },
          { text: '年齢', 
            value: 'age' 
          },
          {
            text:'削除',
            value:'delete',
            sortable:false
          }
        ],
```

sortable:falseにするとソートできなくなります。
削除でソートすることはないのでfalseにしておきます。

items配列の中のオブジェクトにdeleteというkeyを持った何かを定義するのはくたびれるので、突っ込んでしまいます。

```vue:main.vue
<template>
  <v-container>
    <v-row>
      <v-col cols="10">
        <v-data-table
          :headers="headers"
          :items="items"
        >
        <template v-slot:item.delete="{ item }">
          <v-btn
            small
            color="error"
            @click="deleteItem(item)"
          >
            delete
          </v-btn>
        </template>
        </v-data-table>
        
      </v-col>
      </v-row>
  </v-container>
</template>
```
tableのslotを使ってdeleteに関して、deleteItemというイベントを持ったボタンを定義します。
これで削除の列にはこの削除ボタンが表示されます。



```vue:main.vue
  methods: {
   deleteItem (item) {
    const index = this.items.indexOf(item)
    confirm('ガチで削除しますか') && this.items.splice(index, 1)
   },
```

処理は公式のをあれしました。
インデックス番号を取得して、確認メッセージを出して、OKならそこを取り除いています。



## axiosを使ってサーバーからitem情報を取得する

テーブルの中身(items)はサーバーから取得してきて表示することも簡単です。
今回は便利な
https://jsonplaceholder.typicode.com/
を利用します。

テーブルの設定を少し変更します。
itemsをserverDatasという配列にしておきます。

```vue:main.vue
<template>
  <v-container>
    <v-row>
      <v-col cols="10">
        <v-data-table
          :headers="headers"
          :items="serverDatas"
        >
        <template v-slot:item.delete="{item}">
          <v-btn
            small
            color="error"
            @click="deleteItem(item)"
          >
            delete
          </v-btn>
        </template>
        </v-data-table>
        
      </v-col>
      </v-row>
  </v-container>
</template>
```

serverDatasというitemsを使うように変更していますので
serverDatasを追加します。

また、今回取得するデータにageがないのですが、emailが取れるので
headersのageをemailに変更しておきます。



```vue:main.vue
      headers: [
          { 
            text: 'ID', 
            value: 'id' 
          },
          {
            text: '名前',
            value: 'name',
          },
          { text: 'メルアド', 
            value: 'email' 
          },
          {
            text:'削除',
            value:'delete',
            sortable:false
          }
        ],
      serverDatas:[

      ],
```


次にaxiosを使ってデータを取得します。
mountedの中でやればページが表示される頃にはデータが取得できていることでしょう。


```vue:main.vue
  mounted(){

    axios.get('https://jsonplaceholder.typicode.com/users')
        .then( res => {
          this.serverDatas = res.data
        })
        .catch( e => {
          console.log(e)
        })
        .finally(()=>{
          console.log("通信完了")
        })
  }
```
これだけです。
serverDatasを取得してきたdataに置き換えました。




<img width="734" alt="スクリーンショット 2019-11-26 7.48.53.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/201764/1e235f2b-dfe8-62de-0d1a-ac69dd9063f3.png">


しっかりデータを取得してテーブルに表示できています。


簡単におしゃれなテーブルが利用できて便利です。



最後にソースを全て貼っておきます。


```vue:main.vue
<template>
  <v-container>
    <v-row>
      <v-col cols="10">
        <v-data-table
          :headers="headers"
          :items="serverDatas"
        >
        <template v-slot:item.delete="{item}">
          <v-btn
            small
            color="error"
            @click="deleteItem(item)"
          >
            delete
          </v-btn>
        </template>
        </v-data-table>
        
      </v-col>
      </v-row>
  </v-container>
</template>

<script>

import axios from 'axios';

export default {

  data(){
    return {
      headers: [
          { 
            text: 'ID', 
            value: 'id' 
          },
          {
            text: '名前',
            value: 'name',
          },
          { text: 'メルアド', 
            value: 'email' 
          },
          {
            text:'削除',
            value:'delete',
            sortable:false
          }
        ],
      serverDatas:[

      ],
      
      items:[
        { 
          id : 1 , 
          name : "高田健志" , 
          age : 33 
        },
        { 
          id : 2 , 
          name : "横山緑" , 
          age: 42
        },
        { 
          id : 3 , 
          name : "山田太郎" , 
          age: 10
        },
      ],
      
    }
  },

  methods: {
   deleteItem (item) {
    
    const index = this.serverDatas.indexOf(item)
    confirm('ガチで削除しますか') && this.serverDatas.splice(index, 1)
   },

  },
  mounted(){

    axios.get('https://jsonplaceholder.typicode.com/users')
        .then( res => {
          this.serverDatas = res.data
        })
        .catch( e => {
          console.log(e)
        })
        .finally(()=>{
          console.log("通信完了")
        })
  }

}
</script>
```

デリートのメソッドは、対象の配列がitemsからserverDatasに変更してあります。