Nuxt.jsでカレンダー予定管理機能を導入
なにかいいものはないかと探していたら、fullcalendarを見つけた。jQueryに依存していないV4のbeta版がでているとのことでそちらを今回導入してみました。
※予定では3月15日に正規版がリリースされるみたいです。
ソース
https://github.com/sauzar18/fullcalendar-v4-nuxt
環境
- Nuxt.js v2.4.5
- Express.js v4.16.4
- backpack-core
- Fullcalendar v4 beta
Nuxt.jsを導入
公式ドキュメント参照
Nuxt.js
こちらから導入方法がわかります。
backpack-coreの設定は下記参照
https://qiita.com/sauzar18/items/32a8553587e2bdcf3689
1.Fullcalendarベースのモジュールをインストール
yarn add @fullcalendar/core @fullcalendar/daygrid
これを導入すると下記ができるようになります。
https://fullcalendar.io/docs/v4/daygrid-view-demo
ここから追加したい機能に応じてモジュールをインストールしていきます。
今回は下記をインストールしました。
- moment.jsの特徴を引き継いでいるmomentプラグイン
- 時間ごとに予定が管理できるtimegridプラグイン
- データのやり取り(クリックアクションでデータをゲットするなど)interactionプラグイン
yarn add @fullcalendar/moment @fullcalendar/timegrid @fullcalendar/interaction
インストール完了したらvueファイルの設定
2. Vueファイル設定
<template>
<div>
<main>
<div id="calendar" />
</main>
</div>
</template>
<script>
export default {
head() {
return {
link: [
{ rel: 'stylesheet', href: '/css/fullcalendar.min.css' }
]
}
},
data() {
return {
events: [
{ title: 'event1', start: '2019-02-27' },
{ title: 'event2', start: '2019-02-28T12:00', end: '2019-02-28T14:00' },
{ title: 'event3', start: '2019-02-28T12:30:00', allDay: false }
]
}
},
created() {
this.$store.commit('setEvents', this.events)
}
}
</script>
こんな感じでVueファイルを設定していきます。
Rest apiなどasync awaitを使ってeventsデータを読み込んだ方が実用的なので、その方法も記載
<template>
<div>
<main>
<div id="calendar" />
</main>
</div>
</template>
<script>
export default {
async asyncData ({ app, store, params }) {
const data = await app.$axios.$get(`/api/get_schedule/${store.state.authUser.userid}`)
store.commit('setEvents', data)
},
head() {
return {
link: [
{ rel: 'stylesheet', href: '/css/fullcalendar.min.css' }
]
}
}
}
</script>
ここでやっていることは
- カレンダーを表示する箇所にidを設置
- イベントデータを読み込んでstoreで状態管理
- fullcalendarのインストール版に入っているcssを読み込む
3. storeの設定
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export const state = () => ({
events: null
})
export const mutations = {
setEvents(state, data) {
state.events = data
}
}
4. pluginsでfullcalendarを読み込み
import { Calendar } from '@fullcalendar/core'
import dayGridPlugin from '@fullcalendar/daygrid'
import momentPlugin from '@fullcalendar/moment'
import timeGridPlugin from '@fullcalendar/timegrid'
import interactionPlugin from '@fullcalendar/interaction'
import jaLocale from '@fullcalendar/core/locales/ja' // 日本語に対応させるために読み込む
export default function (context) {
if (document.querySelector('#calendar')) {
document.addEventListener('DOMContentLoaded', function () {
const calendarEl = document.querySelector('#calendar')
const calendar = new Calendar(calendarEl, {
locale: jaLocale,
height: 625,
events: context.store.state.events,
plugins: [dayGridPlugin, momentPlugin, timeGridPlugin, interactionPlugin],
defaultView: 'dayGridMonth',
editable: true,
selectable: true,
selectHelper: true,
ignoreTimezone: false,
header: {
left: 'today prev,next',
center: 'title',
right: 'dayGridMonth,timeGridWeek,timeGridDay'
},
eventLimit: true,
firstDay: 0,
weekends: true,
weekMode: 'fixed',
weekNumbers: false,
slotDuration: '00:30:00',
snapDuration: '00:15:00',
allDaySlot: false,
allDayText: 'allday',
slotMinutes: 15,
snapMinutes: 15,
slotLabelFormat: 'H:mm',
firstHour: 9,
defaultTimedEventDuration: '10:00:00',
axisFormat: 'H:mm',
timeFormat: 'H:mm',
minTime: '00:00:00',
maxTime: '24:00:00',
buttonText: {
prev: '',
next: '',
prevYear: '',
nextYear: ''
},
eventClick: function (info) {
alert('Event: ' + info.event.title)
alert('Coordinates: ' + info.jsEvent.pageX + ',' + info.jsEvent.pageY)
alert('View: ' + info.view.type)
// change the border color just for fun
info.el.style.borderColor = 'red'
},
dateClick: function (info) {
alert('Clicked on: ' + info.dateStr)
alert('Coordinates: ' + info.jsEvent.pageX + ',' + info.jsEvent.pageY)
alert('Current view: ' + info.view.type)
info.dayEl.style.backgroundColor = 'red'
}
})
calendar.render()
})
}
}
ここでやっていること
- モジュールをimport
- 日本語対応
- storeを使えるようにexport defaultをつかう
- id(#calendar)があるページのみスクリプトが着火
- 公式ドキュメント通りに各種設定
locale
言語設置
height
コンテンツの高さの設定
events
イベント情報の設定
plugins
利用するモジュールの設置
defaultview
デフォルトの表示設定
editable
カレンダーの予定を変更できるかどうか
selectable
クリックしてドラッグすることで、ユーザーが複数の日またはタイムスロットを強調表示できるようにする
selectHelper
ユーザーがドラッグしている間に「プレースホルダー」イベントを描画するかどうか。
ignoreTimezone
UTCオフセットを無視するかどうか
header
カレンダーの上部にあるボタンとタイトルを定義
eventLimit
1日に表示されるイベントの数を制限。残りはポップオーバーに表示。
firstDay
毎週始まる日の設定。
日曜日= 0、月曜日= 1、火曜日= 2など
weekends
土曜日/日曜日の列をいずれかのカレンダービューに含めるかどうか。
weekMode
月ビューに表示される週数を決定
weekNumbers
週番号をカレンダーに表示するかどうか
slotDuration
タイムスロットを表示する頻度。
snapDuration
ドラッグされたイベントが時間軸にスナップする時間間隔。
allDaySlot
「終日」スロットをカレンダーの上部に表示するかどうか
allDayText
カレンダー上部の「終日」のスロットにタイトルを付けるテキスト
slotMinutes
タイムスロットを表示する頻度(分単位)。
snapMinutes
ドラッグされたイベントがアジェンダビューのタイムグリッドにスナップする間隔。
slotLabelFormat
タイムスロット内に表示されるテキスト
firstHour
スクロール区画に表示される最初の1時間を決定
defaultTimedEventDuration
値が指定されていない時限イベントオブジェクトのフォールバック期間
axisFormat
アジェンダビューの垂直軸に表示されるタイムテキストを決定
timeFormat
各イベントに表示される時間テキストを決定
minTime
毎日表示される最初のタイムスロットを決定
maxTime
毎日表示される最後のタイムスロットを決定
buttonText
ヘッダー/フッターのボタンに表示されるテキスト
eventClick
ユーザーがイベントをクリックしたときに発生
※ここでquerySelectorなどをつかって値を入れてもいいし、試してないけど、storeにいれた管理してもよいかと
dayClick
ユーザーが日付または時刻をクリックしたときに発生
他にも設定できることは沢山あります。詳しくはDoc参照
5. nuxt.config.js設定
pluginの読み込み
plugins: [
{ src: '~/plugins/calendar.js', ssr: false }
],
eslintなどでfullcalendarが使えない場合
build: {
/*
** You can extend webpack config here
*/
extend(config, ctx) {
// Run ESLint on save
if (process.server && process.browser) {
config.module.rules.push({
enforce: 'pre',
test: /\.(js|vue)$/,
loader: 'eslint-loader',
exclude: /(node_modules)/
})
}
}
}
これでカレンダーが表示されれば設置完了です。
まとめ
v4の本リリース後またソースの修正が必要になると思う
storeを使ってフロントに描写するかdocument.querySelectorなどDOMの操作を使って描写するといいかも
もっといい方法があるかもしれないのである方は共有お願いします。