Vue3 DatePickerを使ってみるついでにmonthPickerとtimePickerで詰まった話

（以前社内ブログに投稿していた記事の再掲です）

Vue3 DatePickerを使用してみたので、簡単にまとめてみました。

その際、monthPickerとtimePicker使用時に公式のドキュメントで解説されていない点で詰まったのでそれらもまとめておきました。

# **はじめに**

元々はVuetify3でDatePickerを使用したかったのですが、を見る限り記事投稿時点では未対応のようでした。
（現在のVuetify3では対応済みですので使えます。[こちら](https://vuetifyjs.com/en/components/date-pickers/#usage)）

そこで代替案として、**Vue3 DatePicker**を使用することにしました。

### **Vue3 Datepickerとは**

公式サイトは[こちら](https://vue3datepicker.com)です。

名前の通り、Vue3でDatePickerを使用するためのライブラリです。

以下のような感じで、簡単に日付選択欄を作成することが出来ます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3681767/58b25914-b5e6-0aa6-b2d9-405b4ad69c98.png)


# **使用手順**

### **１．インストール**

[公式の手順](https://vue3datepicker.com/installation/)に従ってインストールしていきます。

yarnコマンドまたはnpmコマンドを使用して@vuepic/vue-datepickerをインストールします。

```bash
yarn add @vuepic/vue-datepicker
```

```bash
npm install @vuepic/vue-datepicker
```

### **２．アプリケーション内に登録**

**ローカルファイルに登録する場合**

使用したいvueファイルの`<script>`タグ内に以下のように記載することで使用できます。

```sample.vue
<script setup>
  import Datepicker from '@vuepic/vue-datepicker'
  import '@vuepic/vue-datepicker/dist/main.css'
</script>
```

**グローバルに登録する場合**

以前書いた記事の方法でファイルを構築している場合は`plugin.js`に以下の通り登録します。

こうすることで、vueファイルの`<script>`内でいちいちimportする手間が省けるのでオススメです。

```sample.vue
<script>
    import { defineNuxtPlugin } from '#app'
    import { createVuetify } from 'vuetify'
    import * as appAll from 'vuetify/components'
    import Datepicker from '@vuepic/vue-datepicker'
    import '@vuepic/vue-datepicker/dist/main.css'
    
    export default defineNuxtPlugin((nuxtApp) => {
      const vuetify = createVuetify({
        components: {
          ...appAll
        }
      })
      nuxtApp.vueApp.use(vuetify)
      nuxtApp.vueApp.component('Datepicker', Datepicker)
    })
</script>
```

以上で準備完了です。

# **実際に使用する**

準備が整ったので使用してみましょう。今回はカードの中にDatePickerを配置してみました。

v-modelで選択した日付を表示しています。

```sample.vue
<template>
  <v-row justify="center" style="height: 800px">
    <v-card width="500" height="80" *class*="mt-16 pa-5">
      <Datepicker v-model="date" />
    </v-card>
  </v-row>
</template>

<script setup>
  import { ref } from 'vue';

  const date = ref();
</script>
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3681767/30302e55-b449-8bca-e663-9227e850d3f5.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3681767/54997de6-adc9-4538-4da1-1adabf3cf4ea.png)


### **表示形式をカスタマイズ**

折角なのでもう少し触ってみます。

表示される日付の形式をカスタマイズしたいと思います。これには[formatプロパティ](https://vue3datepicker.com/api/props/#format)を使用します。

```sample.vue
<template>
  <v-row justify="center" style="height: 800px">
    <v-card width="500" height="80" *class*="mt-16 pa-5">
      <Datepicker
        v-model="date"
        :format="format"
      />
    </v-card>
  </v-row>
</template>

<script setup>
  import { ref } from 'vue';
  const date = ref();
  const format = args => {
    return `${args.getFullYear()}年${args.getMonth() + 1}月${args.getDate()}日`}
</script>
```

デフォルト表示

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3681767/b9f77a4f-94ce-5690-2e21-395b4baf7004.png)

format追加後の表示

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3681767/5530c1c8-25b1-c3ff-11b4-4ac7f029c171.png)

このような感じで、表示される日付のフォーマットを変更することが出来ます。

### **monthPickerとtimePickerと使用上の注意点**

年月のみ選択する[monthPicker](https://vue3datepicker.com/api/props/#monthpicker)と、時刻のみ選択する[timePicker](https://vue3datepicker.com/api/props/#timepicker)も使用できます。

そして、先ほどのデフォルトのDatePickerとformat指定の仕様が少し異なります。(ドキュメントには書いておらず少し大変でした。)

使い方としては、どちらも以下のように追記するだけで使用できます。

```sample.vue
// monthPicker
<Datepicker monthPicker />
// timePicker
<Datepicker timePicker />
```

monthPicker
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3681767/6a4763b2-0d93-c349-80b8-0c304dbe6bd2.png)


timePicker

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3681767/fee2483b-6d66-0656-e5d1-2728bf598a15.png)


折角ならこの二つの表示形式も変更したいですよね。

そこで、先程と同じようにformatプロパティを使用して表示形式を変更します。

```sample.vue
<template>
  <v-row justify="center" style="height: 800px">
    <v-card width="500" height="80" *class*="mt-16 pa-5">
      <Datepicker
        v-model="date"
        :format="format"
        monthPicker
      />
    </v-card>
  </v-row>
</template>

<script setup>
  import { ref } from 'vue';
  const date = ref();
  const format = args => {
    return `${args.getFullYear()}年${args.getMonth() + 1}月`}
</script>
```

すると、Uncaught (in promise) TypeError: args.getFullYear is not a functionというエラーが発生してしまいました。

ちなみに、timePickerでもargs.getFullYearの部分は違いますが上記と同様のエラーが発生します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3681767/38e6d09a-5ccb-e03f-be62-d796a6d409e4.png)

**原因**

**デフォルト状態で選択した日時の型と、monthPicker , timePickerで選択した日時の型が異なることが原因**ではないかと思われます。

DatePickerがデフォルトの状態だと選択された日付はDate型として扱われているのですが、monthPickerやtimePickerなどを使用した場合は以下のようなオブジェクト形式で扱われています。そのため、getFullYear()などは使用できません。

monthPicker使用時

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3681767/75db3be8-b1e0-0775-e468-b08d059de5d4.png)

**解決策**

ここまで分かれば後は単純です。既にオブジェクト内で年月や日時に分けられているので、それを普通に持ってくるだけです。

```sample.vue
<script>
  // monthPickerの場合
  const format = (args) => {
    return `${args.year}年${args.month + 1}月`
  }
  // timePickerの場合
  const format = (args) => {
    return `${args.hours}時${args.minutes}分${seconds}秒`
  }
</script>
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3681767/f1f35341-0379-3346-e456-a7be7be433e6.png)

これで無事、フォーマットの変更が出来ました。

monthPickerとtimePicker使用時にはformat設定時など、選択された値に対して何かする場合は少し注意が必要だと覚えておいてください。

Vue3DatePickerには他にも様々な機能があるので、[公式のページ](https://vue3datepicker.com/api/props/)でチェックしてみてください。

# **参考**

[https://github.com/vuetifyjs/vuetify/issues/14984](https://github.com/vuetifyjs/vuetify/issues/14984)

[https://vue3datepicker.com/](https://vue3datepicker.com/)