今回のお題は、カレンダーのカスタマイズと週や日単位で表示するビューの追加です。でき上がりの動きやコードは、CodeSandboxに公開したつぎのサンプル001でお試しいただけます。
サンプル001■
イベントの要素をカスタマイズする
まず、カレンダーに予定として示される、イベントの要素をカスタマイズしてみましょう。そこで、FullCalendar
コンポーネントに加えるのがeventContent
です(「Content Injection」参照)。定めたコールバック(renderEventContent
)から、差し込むJSX要素を返してください。受け取る引数(eventContent
)は、イベントの情報を収めたオブジェクトです。プロパティのtimeText
は時刻を示す文字列、event
からイベントオブジェクトが得られます。
import FullCalendar, {
EventContentArg,
} from "@fullcalendar/react";
const renderEventContent = (eventContent: EventContentArg) => (
<>
<b>{eventContent.timeText}</b>
<i>{eventContent.event.title}</i>
</>
);
function App() {
return (
<div className="demo-app">
<div className="demo-app-main">
<FullCalendar
eventContent={renderEventContent}
/>
</div>
</div>
);
}
これで、カレンダーの予定に、カスタマイズした要素が差し込まれます。
図001■カスタマイズしたイベントの表示
ヘッダーのタイトルやボタンをカスタマイズする
つぎは、ヘッダー部にあるタイトルやボタンのカスタマイズです。そのボタンの中に、ビューの切り替えを加えます。そのために、TimeGridビューのプラグインをインストールしてください。このあと、モジュールにimport
したうえで、FullCalendar
コンポーネントのplugins
の配列に加えます。
npm install --save @fullcalendar/timegrid
ヘッダーに置く項目の位置を、左(start
)/中央(center
)/右(end
)に割り振るのが、FullCalendar
に加えるheaderToolbar
です。つぎのように配置することにします。
- 左(
start
): 月の前後移動と今月表示ボタン - 中央(
center
): 月タイトル - 右(
end
): 月/週/日のビュー切り替えボタン
import timeGridPlugin from "@fullcalendar/timegrid";
function App() {
return (
<div className="demo-app">
<div className="demo-app-main">
<FullCalendar
// plugins={[dayGridPlugin, interactionPlugin]}
plugins={[dayGridPlugin, timeGridPlugin, interactionPlugin]}
headerToolbar={{
start: "prev,next today",
center: "title",
end: "dayGridMonth,timeGridWeek,timeGridDay",
}}
/>
</div>
</div>
);
}
ヘッダーの項目の位置が変わるとともに、新たに月/週/日のビューの切り替えボタンが加わりました。
図002■カスタマイズされたヘッダー
カレンダーにオプションのプロパティを加える
FullCalendar
コンポーネントには、さまざまなオプションのプロパティが備わっています。今回、つぎの表001の4つのプロパティを加えてみました。これらの値はすべて真偽値で、デフォルト値はfalse
です。
表001■FullCalendar
コンポーネントのオプションプロパティ
プロパティ | 説明 |
---|---|
selectMirror |
TimeGridビューで、イベント作成中にプレースホルダーを表示するかどうかの真偽値。デフォルト値はfalse 。 |
dayMaxEvents |
DayGridビューで、日付の高さを固定するかどうかの真偽値。固定すると、表示しきれないイベントは件数が示される。デフォルト値はfalse 。 |
navLinks |
日付にリンクを加えるかどうかの真偽値で、リンク先は日付のビュー。デフォルト値はfalse 。 |
businessHours |
平日の営業時間とそれ以外の表示を区別するかどうかの真偽値。デフォルト値はfalse 。 |
function App() {
return (
<div className="demo-app">
<div className="demo-app-main">
<FullCalendar
selectMirror={true}
dayMaxEvents={true}
navLinks={true}
businessHours={true}
handleWindowResize={true}
/>
</div>
</div>
);
}
ルートモジュールsrc/App.tsx
の記述は、つぎのコード001にまとめたとおりです。冒頭にリンクしたサンプル001のCodeSandboxで動きやコードをお確かめください。
コード001■ルートモジュール
import { useCallback, useState } from "react";
import FullCalendar, {
DateSelectArg,
EventApi,
EventClickArg,
EventContentArg,
} from "@fullcalendar/react";
import dayGridPlugin from "@fullcalendar/daygrid";
import allLocales from "@fullcalendar/core/locales-all";
import interactionPlugin from "@fullcalendar/interaction";
import timeGridPlugin from "@fullcalendar/timegrid";
import { INITIAL_EVENTS, createEventId } from "./event-utils";
function App() {
const [currentEvents, setCurrentEvents] = useState<EventApi[]>([]);
const handleEvents = useCallback(
(events: EventApi[]) => setCurrentEvents(events),
[]
);
const handleDateSelect = useCallback((selectInfo: DateSelectArg) => {
let title = prompt("イベントのタイトルを入力してください")?.trim();
let calendarApi = selectInfo.view.calendar;
calendarApi.unselect();
if (title) {
calendarApi.addEvent({
id: createEventId(),
title,
start: selectInfo.startStr,
end: selectInfo.endStr,
allDay: selectInfo.allDay,
});
}
}, []);
const handleEventClick = useCallback((clickInfo: EventClickArg) => {
if (
window.confirm(`このイベント「${clickInfo.event.title}」を削除しますか`)
) {
clickInfo.event.remove();
}
}, []);
const renderEventContent = (eventContent: EventContentArg) => (
<>
<b>{eventContent.timeText}</b>
<i>{eventContent.event.title}</i>
</>
);
return (
<div className="demo-app">
<div className="demo-app-main">
<FullCalendar
plugins={[dayGridPlugin, timeGridPlugin, interactionPlugin]}
headerToolbar={{
start: "prev,next today",
center: "title",
end: "dayGridMonth,timeGridWeek,timeGridDay",
}}
initialView="dayGridMonth"
eventContent={renderEventContent}
selectable={true}
editable={true}
selectMirror={true}
dayMaxEvents={true}
navLinks={true}
businessHours={true}
initialEvents={INITIAL_EVENTS}
locales={allLocales}
locale="ja"
eventsSet={handleEvents}
select={handleDateSelect}
eventClick={handleEventClick}
/>
</div>
</div>
);
}
export default App;
シリーズ
「FullCalendar React+TypeScript Example Projectを関数コンポーネントで書いてみる 01」
「FullCalendar React+TypeScript Example Projectを関数コンポーネントで書いてみる 03」