DatePicker: Vuetify3 の新コンポーネント (labs) を試す

# 内容

DataPicker は表示されたカレンダーから日付を選択できる UI を提供するコンポーネントです。

# 前提

Vuetify のバージョンは 3.4.6 で試しています。バージョンが上がると仕様は変更されるかもしれません。

# 公式

- [DataPickers](https://vuetifyjs.com/en/components/date-pickers/)

## 基本

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266247/3b1f5672-17cb-47f8-ac87-57dc37bad87c.png)

```DataPicker.vue
<template>
  <v-container>
    <v-date-picker
      v-model="dateValue"
      @click:save="saveDate()"
      @click:cancel="cancelDate()"
      @update:modelValue="updateDate()"
    >
    </v-date-picker>
    <div>{{dateValue[0]}}</div>
  </v-container>
</template>

<script>
export default {
    data: () => ({
      dateValue: [],
    }),
    methods: {
      saveDate() {
        // これは意図通りに動作しない
        console.log('save: ', this.dateValue[0])
      },
      updateDate() {
        console.log('update: ', this.dateValue[0])
      },
      cancelDate() {
        // これは意図通りに動作しない
        console.log('cancel: ', this.dateValue[0])
      },
    },
  }
</script>
```

"OK" を押したときの日付の取得は `@update:modelValue` と `v-model` を使います。日付は Array で帰ってきます。

`@click:save` というイベントがありますが、これを使うと意図通りの動作にはなりません。`@click:cancel` も同様です。現状、日付の取得は `@update:modelValue` で行う必要があるようです。

おそらく、これはこういう仕様です。

コードの動作は下記で確認できます。

- [play.vuetifyjs.com: DatePicker](https://play.vuetifyjs.com/#eNqlU8FuozAQ/ZWRLwlSDNlmDxVKo6y037CXkAOFaeMtNpZtaFcR/75jY1KaqlKknoA3b96beTaHM/ulddp3yHK2dSh1UzrcFQpg2/OqVa4UCk0AAlRTmWtRvaAZMYCey7bG5qFgvvinbDos2FTcVw2Rc1v2SAT/+E2kZTJjdNr35UEkdBNxxK6puSzfqKjwFUJpcbe+2/D1PV//WCTpM7qPDdPU2YexJ7QW/e58vox8WB+HYZt5NGxPTfP1t9ksHPq0lRHaBSq+6dY4qPGp7BoH51GfhMsclgk87GAZsYCOdjkcjqsRHZL4ItGd2trmkwTAe17vGADNZdsG06Z9Xi48JYfFCtxJ2HS+TjJ1DFEfYB7rl4rxPG7THJ+DD+gSCVsxIX0mXJY6/WtbRZcruBWxYAt22bJgdPv8d8FOzmmbZ1lVK2qj6yB6kyp0mdIy2xMtM51yQiKvW7nfpJv0Jx2YdXM4RSv5o2lfLRoSKVgcNNg48fTvBqvIDA73o0OEeFM+Wm/xSTojvx4NN6hqNPR33LjRVdt8q6vSp81i8gPl3Qj1Yq+irmyI+TAN+a2Vg5hXOnrDYcXCnOQcGtjxP2UpYcI=)


## 複数選択
 
`multiple` prop を使うと shuft キーを押すことで、日付を範囲で選択できるようになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266247/8aa81e70-ef24-f565-8976-a4913d04a124.png)

```.vue
    <v-date-picker
        multiple
    >
    </v-date-picker>
```

こんなかんじです。

## 影付き

`elevation` prop を使います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266247/3e88605e-7a64-429f-0def-ac85fecf32c3.png)

```.vue
    <v-date-picker
       elevation="24"
    >
    </v-date-picker>
```

## 前後の月の日付も表示

`show-adjacent-months` prop を使います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266247/a3535151-9825-70a5-8e9b-5c7256eb945a.png)

```.vue
    <v-date-picker
       show-adjacent-months
    >
    </v-date-picker>
```

## ローカライズ

`yarn add @date-io data-fus` が必要です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266247/e4036085-a19f-d613-d79d-9c8d56fcabe7.png)

日付の表示だけ日本語になります。OKとかCANCELは日本語になりません。

```.vue
<template>
  <v-container>
    <v-date-picker
      v-model="dateValue"
      @update:modelValue="updateDate()"
    >
    </v-date-picker>
    <div>{{dateValue[0]}}</div>
  </v-container>
</template>

<script>
import DateFnsAdapter from '@date-io/date-fns'
import enUS from 'date-fns/locale/en-US'
import jaJP from 'date-fns/locale/ja'

export default {
  date: {
    adapter: DateFnsAdapter,
    locale: {
      en: enUS,
      ja: jaJP,
    },
  },
  data: () => ({
    dateValue: [],
  }),
  created: function(){
    this.$vuetify.locale.current = 'ja';
  },
  methods: {
    updateDate() {
      console.log('update: ', this.dateValue[0]);
    },
  },
}
</script>
```

OKとかも変えたければ、自力で指定する必要があります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266247/ef24bd28-c08c-46d5-4cec-da7b295382c1.png)

```.vue
<template>
  <v-container>
    <v-date-picker
      v-model="dateValue"
      @update:modelValue="updateDate()"
      title="日付の選択"
      ok-text="設定"
      cancel-text="取り消し"
    >
    </v-date-picker>
    <div>{{dateValue[0]}}</div>
  </v-container>
</template>

<script>
import DateFnsAdapter from '@date-io/date-fns'
import enUS from 'date-fns/locale/en-US'
import jaJP from 'date-fns/locale/ja'

export default {
  date: {
    adapter: DateFnsAdapter,
    locale: {
      en: enUS,
      ja: jaJP,
    },
  },
  created: function(){
    this.$vuetify.locale.current = 'jp';
  },
  data: () => ({
    dateValue: [],
  }),
}
</script>
```

## ダイアログ化

閉じるときに `@click:save` と `@click:cancel` を使います。

![datepicker1.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266247/84cbbaca-2c35-3322-f723-91981424197a.gif)

```.vue
<template>
  <v-container class="d-flex">
    <v-row>
      <v-spacer></v-spacer>
      <v-col cols="8">
        <v-text-field readonly v-model="dateValue[0]">
        </v-text-field>
      </v-col>
      <v-col class="d-flex align-center" cols="2">
        <v-btn
          color="primary"
          @click="dialog = !dialog"
        >
          Select Date
          <v-dialog v-model="dialog">
            <v-date-picker
              v-model="dateValue"
              @update:modelValue="updateDate()"
              @click:save="dialog=false"
              @click:cancel="dialog=false"
            >
            </v-date-picker>
          </v-dialog>
        </v-btn>
      </v-col>
      <v-col class="d-flex align-center" cols="2">
        <v-btn @click="dateValue=[]">
          CLEAR
        </v-btn>
      </v-col>
      <v-spacer></v-spacer>
    </v-row>
  </v-container>
</template>

<script>
export default {
  data: () => ({
    dateValue: [],
    dialog: false,
  }),
  methods: {
    updateDate() {
      console.log('update: ', this.dateValue[0])
    },
  }
}
</script>
```

## 色を変える

`color` prop で変更できますが、変わるのは選択された日付の色やボタンのテキストの色だけです。それら以外を変えるには、Vuetify の他のコンポーネントと同様で、自力でゴリゴリ指定する必要がありそうです

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266247/1ff383dc-56ba-5613-89a7-778f2c66356f.png)


```.vue
<v-date-picker
  color="rgba(255, 0, 0, 0.8)"
>
</v-date-picker>
```

## その他

- `boader`: 枠が付きます。影を付けてるとほとんどわかりません。
- `calendar-icon`: 入力モードをカレンダーに切り替える場所のアイコンが変わります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266247/f6d6dd3f-c7c5-d268-419b-771925ead290.png)

右上にある、カレンダーのマークのアイコンです。`calendar-icon="mdi-home"` とか指定すると下記のようになります

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266247/1323e7c0-554f-859c-b58d-59a373fe5c7e.png)

- `hide-actions`: OK と Cancel ボタンがなくなります。日付を選んだときに、すぐに `@update:modelValue` が呼び出され、`v-model` の値が変更されます。

![datepicker2.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266247/1ef7da40-cf47-1832-59d4-5cd204e4e643.gif)

用途によっては、こっちのほうが使いやすいです。

```.vue
  <v-container>
    <v-date-picker v-model="date2"
      hide-actions
    >
    </v-date-picker>
    <div>
      {{date2[0]}}
    </div>
  </v-container>
```

- `max` とか `min` とかは 3.3.7 では指定しても無効っぽいです。

# 参考

- [DataPickers](https://vuetifyjs.com/en/components/date-pickers/)