Next.jsでFullCalenderをカスタマイズ
FullCalendarは、JavaScriptで書かれたオープンソースのイベントカレンダーライブラリです。昔作ったメモアプリにカレンダー導入したくて使ったものを、機能を増やしました。
ちょっと苦労したのと、当時はメモを残していなかったので今回の内容メモです。
カスタマイズする内容
特にそんなに多機能を求めていなかったので、イベントにマウスをホバーするとTooltipでイベントの内容を表示する機能と日本語化だけしていきたいと思います。
ReactだとTooltipを表示させるための情報が少なくて苦労してしまいました。でも1日時間空けてやると拍子抜けするくらい簡単に実装できてしまったので不思議ですね。
メモですので、導入手順も含めて書いていきます。
利用環境
- Next.js 13.2.3
- React 17.0.2
- typeScript 4.3.2
- @fullcalendar/react 5.10.1
- @fullcalendar/core 5.10.1
- @fullcalendar/daygrid 5.10.1
- @fullcalendar/interaction 5.10.1
FullCalendarをインストールする
FullCalendarをインストールするには、npmパッケージマネージャーを使用します。以下のコマンドを使用して、FullCalendarをインストールします。
npm install --save @fullcalendar/react @fullcalendar/daygrid @fullcalendar/core @fullcalendar/daygrid @fullcalendar/interaction
FullCalendarを導入する手順
FullCalendarをカスタマイズするには、以下の手順を実行します。
import FullCalendar from '@fullcalendar/react';
// FullCalendarで月表示を可能にするプラグイン。
import dayGridPlugin from '@fullcalendar/daygrid';
// FullCalendarで日付や時間が選択できるようになるプラグイン。
import interactionPlugin from "@fullcalendar/interaction";
//インポートはプラグインを後にするようにしてください。
FullCalendarコンポーネントをレンダリングします。
//イベントはオブジェクトの配列をPropsとして渡します
const eventExample = [
//オブジェクトの中身はこんな感じ
//satrtとendの日付で日を跨いだ予定を表示できる
//背景のカラーもこの中で指定できる
{
title: "温泉旅行",
start: new Date(),
end: new Date().setDate(new Date().getDate() + 5),
description: "友達と温泉旅行",
backgroundColor: "green",
borderColor: "green"
},
{
title: "期末テスト",
start: new Date().setDate(new Date().getDate() + 5),
description: "2年最後の期末テスト",
backgroundColor: "blue",
borderColor: "blue"
}
];
<FullCalendar
plugins={[dayGridPlugin]}
initialView="dayGridMonth"
events={eventExample}
/>
Next.jsに対応する
Next.jsの仕様によって、node_modules 配下にあるFullCalenderのグローバルCSSが読み込まれないため、このままだとエラーになってしまいます。
エラーの修正はnext-transpile-modules をインストールして next.config.js で設定して対応します。
まずはインストール。
npm i next-transpile-modules
next.config.jsに以下のコードを追加します。
const withTM = require("next-transpile-modules")([
"@fullcalendar/common",
"@fullcalendar/daygrid",
"@fullcalendar/react",
]);
/** @type {import('next').NextConfig} */
module.exports = withTM({
// any other next.js settings here
});
これで対応できるかと思います。
ページを表示してみる
これだけでも十分いいですがもう少しカスタマイズします。
日本語化
日本語にしていくのは最初にインストールした**@fullcalendar/core**を使います。
日本語に対応するためのモジュールをインポートしましょう。
import FullCalendar from '@fullcalendar/react';
// FullCalendarで月表示を可能にするプラグイン。
import dayGridPlugin from '@fullcalendar/daygrid';
// FullCalendarで日付や時間が選択できるようになるプラグイン。
import interactionPlugin from "@fullcalendar/interaction";
//日本語対応のためのインポート
import jaLocale from "@fullcalendar/core/locales/ja"; //追加
//インポートはプラグインを後にするようにしてください。
ヘッダーを少しだけ修正と全体の高さを調整
//イベントはオブジェクトの配列をPropsとして渡します
const eventExample = [
//オブジェクトの中身はこんな感じ
//satrtとendの日付で日を跨いだ予定を表示できる
//背景のカラーもこの中で指定できる
{
title: "温泉旅行",
start: new Date(),
end: new Date().setDate(new Date().getDate() + 5),
description: "友達と温泉旅行",
backgroundColor: "green",
borderColor: "green"
},
{
title: "期末テスト",
start: new Date().setDate(new Date().getDate() + 5),
description: "2年最後の期末テスト",
backgroundColor: "blue",
borderColor: "blue"
}
];
<FullCalendar
plugins={[dayGridPlugin]}
initialView="dayGridMonth"
events={eventExample}
weekends={true} //falseにすると土日が含まれなくなるdefault値がtrueなので省略可
//以下を追加
headerToolbar={{
start: "prevYear,nextYear",
center: "title",
end: "today prev,next"
}}
contentHeight={"700px"}
/>
こんな感じで並び替えて、月と年をそれぞれ移動できるようにしました。
Tooltipでイベントの内容を表示させる
ここに非常にはまりました。ドキュメントを読んでもReact情報少なく、どのHooksを使えばいいのかよくわからなくてエラーを連発しました。
次の日にやったらあっさりできたんですが。。。orz
結論から申しますとeventContentを使ってeventをレンダリングすることで解決できました!
公式では
eventContent
- a Content Injection Input
Generated content is inserted inside
the inner-most wrapper of the event element. If supplied as a callback function, it is called every time the associated event data changes.
eventContent - コンテンツ・インジェクション入力。生成されたコンテンツは、イベント要素の最も内側のラッパーの中に挿入されます。コールバック関数として提供された場合、関連するイベントデータが変更されるたびに呼び出されます。
ちょっと何言ってるかわかんない。
とりあえずコードで動かしてみましょう!
TooltipはChakraUIのTooltipコンポーネントを使いました!他のライブラリでもいいと思います。
//省略
//tooltipを追加するために生成するコンポーネント
const EventComponent = (arg: EventContentArg) => (
<Tooltip
label={arg.event.extendedProps.description} //イベントの中身
aria-label="tooltip"
placement="top-start"
hasArrow
arrowSize={5}
>
<div>{arg.event.title}</div> //イベントのタイトル
</Tooltip>
);
<FullCalendar
plugins={[dayGridPlugin]}
initialView="dayGridMonth"
events={eventExample}
weekends={true} //falseにすると土日が含まれなくなるdefault値がtrueなので省略可
headerToolbar={{
start: "prevYear,nextYear",
center: "title",
end: "today prev,next"
}}
contentHeight={"700px"}
//追加
eventContent={(arg: EventContentArg) => EventComponent(arg)}
/>
このようにホバーするとTooltipで内容が表示されました。
その他いろいろカスタマイズできるようですが、自分には現状必要ないのでまた何か追加したくなったら試してみます。
自前でカレンダーの実装は大変だと思うのでぜひ試してみてください!
参考にさせていただいたサイト
【Next】FullCalendarをNext.jsで使うまでのメモ