
初めてカレンダーライブラリのflatpickrを使ってみたので、その備忘録。
ちょっとした設定だけでカレンダーが実装できて大変嬉しい。
ざっくりかき4つのステップでいけます。
①flatpickrのインストール
②flatpickerのインポート
③テキストフィールドにidを指定
④scriptでオプションを指定
▼環境
- macOS Big Sur 11.2.3
- node v16.2.0
- npm 7.20.0
- nuxt.js @nuxt/cli v2.15.6
また当方、フレームワークはvuetifyを使用しています!
①flatpickrのインストール
getting Started.
まずはnpm i -D flatpickrまたはyarn add flatpickrにてflatpickrをインストール。
CDNでの読み込みも可能です。その他方法のインストールは公式をご参照ください。
flatpickr公式
追記:
nuxt向けにはこんなのもあるみたいです。これを入れると後の実装が変わります。module追記する必要があると思います。
npm | nuxt-flatpickr
npm i nuxt-flatpickr
②flatpickerのインポート
<script>内にflatpickrを宣言します。default必要。
<script>
const flatpickr = require('flatpickr').default
</script>
参考: stackflow | Why need default after require() method in Vue?
③テキストフィールドにidを指定
入力フォームを設置してidを指定します。
inputタグ(今回はvuetifyを使っているのでv-text-fieldを使用)など、入力フォームにidを設定し、data内でidを定義します(id: 'datePick')。
<template>
<div>
<Header />
<v-container>
<v-text-field :id="id"></v-text-field>
</v-container>
</div>
</template>
<script>
const flatpickr = require('flatpickr').default
export default {
data() {
return {
id: 'datePick',
}
},
}
</script>
もちろん、textfieldタグのidに直接定義しても大丈夫です。
<v-text-field id="datePick"></v-text-field>
④scriptでオプションを指定
<script>
const flatpickr = require('flatpickr').default
export default {
data() {
return {
id: 'datePick',
}
},
mounted() {
// DOMが描画されてからflatpickr呼び出し
this.$nextTick(() => {
this.flatpickr = flatpickr('#' + this.id, this.flatPickrConfig)
})
},
}
</script>
せっかくなので拡張してみる。
せっかくなので、親、子、孫、みたいな感じでデータを渡してみます。
getting Startedまでは同じです。
ファイル構成は、下記の通り。
親: pages/date/index.vue
子: components/molecules/ContentsCard.vue
孫: components/Atoms/DatePicker.vue
親で今日の日付を取得
親で今日の日付を取ってきて、初期値として表示。
<template>
<div>
<Header />
<v-container class="contents">
<ContentsCard :today="today" />
</v-container>
</div>
</template>
<script>
export default {
asyncData({ $dayjs }) {
const dayjs = $dayjs()
const today = dayjs.format('YYYY年MM月DD日')
// console.log(today)
return { today }
},
}
</script>
子ども(components/molecules/ContentsCard.vue)を作成
vuetifyのポップアップウィンドウはv-dialogでできます。
https://vuetifyjs.com/ja/components/dialogs/
<template>
<div>
<v-card class="mx-auto" min-width="360" outlined flat>
<v-card-title>This it the flatpickr</v-card-title>
<v-card-subtitle>Click the button then you'll see</v-card-subtitle>
<v-card-text>
<v-dialog v-model="dialog" width="500">
<template #activator="{ on, attrs }">
<v-btn
color="primary"
rounded
elevation="false"
v-bind="attrs"
v-on="on"
>
open dialog
</v-btn>
</template>
<v-card>
<v-card-title class="text-h5"> flatpickr </v-card-title>
<v-card-text> ここに孫のDatePicker.vueを入れるよ!
<v-divider></v-divider>
</v-card-text>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn color="primary" text @click="dialog = false">
close
</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</v-card-text>
</v-card>
</div>
</template>
<script>
export default {
data() {
return {
dialog: false,
}
},
}
</script>
まだ孫を作成していないため、open dialogを押下してもテキストしかありません。

孫(components/atoms/DatePicker.vue)を作成
先ほどのContentsCard.vueのテキストエリア
<v-card-text> ここに孫のDatePicker.vueを入れるよ! </v-card-text>の中身を、
孫のコンポーネント名に書き換えます。
<v-card-text>
<DatePicker3></DatePicker3>
<v-divider></v-divider>
</v-card-text>
今日の日付をデフォルトの表示として孫のテキストフィールドに表示させたいため、propsとして親から受け取った値を孫に渡しておきます。はい、これお小遣いね。
<DatePicker v-model="itemToday" label="日付を選択"></DatePicker>
// 適当なところで日付が取れているか確認
{{ itemToday }}
<script>
export default {
props: {
today: {
type: String,
default: '',
},
},
data() {
return {
dialog: false,
itemToday: '',
}
},
mounted() {
this.itemToday = this.today
},
}
</script>
それではやっと孫の中身を作成し始めます。
何はともあれ土台と、先ほど子どもで受け取った今日の日付を受け取っておきます。
選択した日付はそのまま親に渡すデータになるので、v-modelはvalueとして値を取得後、computedで値をセットして$emitしておきます。(親は@inputで受け取れます。)
※v-modelによるプロパティのバインディングは、:value(部品の初期値を指定)と@input(データとしてサーバに送信)をまとめた等位構文なので。バインドしたプロパティに対して参照と更新の両方が発生。
参考: v-modelにオブジェクトをバインディングする場合のコンポーネント実装を考える
valueで複数型を指定しているのは、$dayjs()で渡される値がStringとNumberの可能性があるからです。
参考: Vue.js の props の type 指定時に String と Number の両方を許容させる
<template>
<div>
<v-text-field v-model="innerValue" :label="label"></v-text-field>
</div>
</template>
<script>
export default {
props: {
value: {
type: [String, Number],
default: '',
},
label: {
type: String,
default: '',
},
},
computed: {
innerValue: {
get() {
return this.value
},
set(val) {
this.$emit('input', val)
},
},
},
}
</script>
孫(components/atoms/DatePicker.vue)にflatpickrを実装!
前置きが長くなってしまったのでお忘れかもしれませんが…flatpickrを実装する上で必要なのは、
①flatpickrのインストール
②flatpickerのインポート
③テキストフィールドにidを指定
④scriptでオプションを指定
でした!
①はもうできているので、
②flatpickerのインポート
const flatpickr = require('flatpickr').default
// export defaultの上
#### ③テキストフィールドにidを指定
そのままidの値を入れてもいいのですが、拡張性を持たせるためにプロパティで用意しておきます。
<v-text-field :id="id" v-model="innerValue" :label="label"></v-text-field>
初期値を設定しておきます。
<script>
export default {
props: {
// propsに追加
id: {
type: String,
default: 'datePick',
},
},
</script>
#### ④scriptでオプションを指定
flatpickrの初期値と、オプションをオブジェクトで用意しておきます。日本語対応させたいので、flatpickrが用意している日本語もimportしておきます。
※オプションは公式をご参照ください。
https://flatpickr.js.org/options/
<script>
import { Japanese } from 'flatpickr/dist/l10n/ja'
export default {
data() {
return {
flatpickr: null,
flatpickrConfig: {
altInput: true,
locale: Japanese,
altFormat: 'Y年m月d日',
dateFormat: 'Ymd',
},
}
},
}
</script>
mountedのタイミングで、flatpickrを描画させます。
$nextTickはVueが用意している機能です。
Callbackを延期し、DOMの更新サイクル後に実行します。DOM更新を待ち受けるために、いくつかのデータを変更した直後に使用してください。
こちらを参考にしました。
Vue.nextTickのコードリーディング
<script>
mounted() {
this.$nextTick(() => {
this.flatpickr = flatpickr('#' + this.id, this.flatPickrConfig)
})
},
methods: {},
}
</script>
おまけ:オシャレにします。
お好みのスタイルを選ぶんだ! => 公式
scriptにテーマを追加するだけ!
<script>
import 'flatpickr/dist/themes/confetti.css'
</script>
初期値、オプション設定
flatpickrの基本は、データの初期値を用意して、オプションを設定するだけ。
私はvuetifyを使用しているため少しわかりにくいかもしれませんが、基本は下記の形です!
<script>
<input class="input" id="unchi" type="text" />
<script>
flatpickr("#unchi", { オプション });
</script>
オプションは公式から確認できます。 => オプション




