はじめに (対象読者・この記事でわかること)

この記事は、FullCalendarを使ってWebアプリケーションにカレンダー機能を実装している、またはこれから実装を考えている開発者の皆さんを対象にしています。特に、FullCalendarの定期イベント(Recurring Events)における dow プロパティの活用と、その一部を特定の条件で非表示にする方法について知りたい方に役立つでしょう。

この記事を読むことで、FullCalendarで曜日指定の定期イベントを設定しつつ、祝日や特定の例外日にそのイベントを表示させないといった、より柔軟なカレンダー表示を実装できるようになります。例えば、「毎週月曜日の定例会議」を設定しているが、祝日の月曜日は表示したくない、といった具体的なニーズに応えるための技術を習得できます。

前提知識

この記事を読み進める上で、以下の知識があるとスムーズです。 * HTML/CSSの基本的な知識 * JavaScriptの基本的な文法とDOM操作の知識 * FullCalendarの基本的なセットアップとイベント設定方法

FullCalendarにおける定期イベントとdowプロパティ

Webアプリケーションでカレンダー機能を実装する際、毎週決まった曜日に行われる会議や、毎月特定の日に開催されるイベントなど、繰り返し発生する予定を扱うことはよくあります。FullCalendarでは、このような繰り返しイベントを「定期イベント(Recurring Events)」として簡単に設定できる強力な機能を提供しています。

その中心となるのがdow(Days Of Week)プロパティです。dowプロパティは、イベントが繰り返される曜日を数値の配列で指定します。例えば、[1, 4]と指定すれば、月曜日(1)と木曜日(4)にイベントが繰り返されるようになります(日曜日は0)。これにより、データベースに何百ものイベントデータを保存することなく、たった一つのイベント定義で期間内の全ての繰り返しイベントをカレンダーに表示させることが可能です。

しかし、この便利なdowプロパティにも課題があります。例えば、「毎週月曜日の定例ミーティング」を設定しているものの、それが国民の祝日と重なる場合は表示したくない、あるいは特定の期間だけは表示したくない、といったニーズが出てくることがあります。dowはあくまで曜日指定の繰り返しであり、特定の日付をピンポイントで除外するような機能は直接提供されていません。

そこで、この記事では、dowによって定義された定期イベントのうち、特定の条件(ここでは特定の日付)に合致するイベントインスタンスをカレンダー上で「非表示」にする具体的な方法を探ります。これにより、カレンダーの表示をよりスマートにし、ユーザーにとって本当に必要な情報だけを提供する柔軟なUIを実現することを目指します。

dowプロパティの一部上書き(非表示)の実装方法

FullCalendarのdowプロパティで設定した定期イベントの一部を非表示にするには、イベントがカレンダーにレンダリングされる際に介入し、条件に応じてそのイベント要素を操作する必要があります。ここでは、FullCalendarのコールバック関数 eventDidMount を利用して、特定の日付のイベントを非表示にする方法を解説します。

ステップ1: 基本的な定期イベントの設定

まず、FullCalendarを初期化し、dowプロパティを使って定期イベントを設定します。ここでは、毎週月曜日と水曜日に「定例ミーティング」というイベントを繰り返す例を考えます。

Html
<!DOCTYPE html> <html> <head> <meta charset='utf-8' /> <link href='https://cdn.jsdelivr.net/npm/fullcalendar@6.1.13/main.min.css' rel='stylesheet' /> <script src='https://cdn.jsdelivr.net/npm/fullcalendar@6.1.13/index.global.min.js'></script> <style> body { margin: 40px 10px; padding: 0; font-family: Arial, Helvetica Neue, Helvetica, sans-serif; font-size: 14px; } #calendar { max-width: 1100px; margin: 0 auto; } </style> </head> <body> <div id='calendar'></div> <script> document.addEventListener('DOMContentLoaded', function() { var calendarEl = document.getElementById('calendar'); var calendar = new FullCalendar.Calendar(calendarEl, { initialView: 'dayGridMonth', headerToolbar: { left: 'prev,next today', center: 'title', right: 'dayGridMonth,timeGridWeek,timeGridDay' }, locale: 'ja', // 日本語化 events: [ { title: '定例ミーティング', startTime: '10:00:00', endTime: '11:00:00', daysOfWeek: [1, 3], // 月曜日(1)と水曜日(3) display: 'block', // デフォルトは表示 color: '#4CAF50' } ] }); calendar.render(); }); </script> </body> </html>

このコードを実行すると、カレンダー上に毎週月曜日と水曜日の午前10時から11時まで「定例ミーティング」が表示されます。

ステップ2: 特定の日(曜日)のイベントを非表示にする

次に、この定期イベントのうち、特定の条件に合致するものを非表示にするロジックを追加します。ここでは、例として「2024年7月29日(月)」と「2024年8月7日(水)」の「定例ミーティング」イベントを非表示にするケースを考えます。

これには、FullCalendarのイベント描画ライフサイクルで提供されるeventDidMountコールバックが最適です。eventDidMountは、各イベントがDOMにマウントされた直後に呼び出されるため、イベント要素(info.el)に直接アクセスし、そのスタイルを変更したり、クラスを追加してCSSで制御したりすることが可能です。

Javascript
document.addEventListener('DOMContentLoaded', function() { var calendarEl = document.getElementById('calendar'); // 非表示にしたい特定の日付リスト // 実際にはAPIなどから取得する想定 const datesToHide = [ '2024-07-29', // 7月29日(月) '2024-08-07' // 8月7日(水) ]; var calendar = new FullCalendar.Calendar(calendarEl, { initialView: 'dayGridMonth', headerToolbar: { left: 'prev,next today', center: 'title', right: 'dayGridMonth,timeGridWeek,timeGridDay' }, locale: 'ja', events: [ { title: '定例ミーティング', startTime: '10:00:00', endTime: '11:00:00', daysOfWeek: [1, 3], // 月曜日(1)と水曜日(3) color: '#4CAF50', id: 'meeting-event' // 非表示対象のイベントを識別するためのID }, // その他のイベントもここに追加可能 ], eventDidMount: function(info) { // info.event は現在のイベントオブジェクト // info.el はイベントのDOM要素 // 非表示にしたいイベントの種類を識別(例: IDでフィルタリング) if (info.event.id === 'meeting-event') { const eventDate = FullCalendar.formatDate(info.event.start, { year: 'numeric', month: '2-digit', day: '2-digit' }).replace(/\//g, '-'); // YYYY-MM-DD 形式に整形 // 非表示リストに含まれているかチェック if (datesToHide.includes(eventDate)) { // イベント要素を非表示にする info.el.style.display = 'none'; // あるいは、クラスを追加してCSSで制御することも可能 // info.el.classList.add('hidden-event'); } } } }); calendar.render(); }); </script> </body> </html>

eventDidMount コールバック内で、以下の処理を行っています。

  1. info.event.id を使って、非表示にしたい対象のイベント(この例では「定例ミーティング」)であるかを確認します。これにより、他のイベントが意図せず非表示になるのを防ぎます。
  2. FullCalendar.formatDate を使用して、イベントの開始日(info.event.start)をYYYY-MM-DD形式の文字列に変換します。これにより、datesToHide配列の文字列と比較できるようになります。
  3. datesToHide.includes(eventDate) で、現在のイベントの日付が非表示リストに含まれているかをチェックします。
  4. 条件が真の場合、info.el.style.display = 'none'; を実行して、イベントのDOM要素を非表示にします。

ハマった点やエラー解決

1. eventDidMount が呼び出されない、または意図したイベントに適用されない

問題: eventDidMountコールバックが動作しない、あるいは特定のイベントにだけ適用したいのに全てに適用されてしまう。 解決策: * FullCalendarのバージョンを確認してください。eventDidMountはFullCalendar v5以降で推奨されています。それ以前のバージョンではeventRenderなどが利用されていましたが、非推奨となっています。 * イベントの識別子(idなど)を適切に設定し、if (info.event.id === 'your-event-id') のような条件分岐で対象イベントを絞り込みましょう。eventDidMountはカレンダーに表示される全てのイベントインスタンスに対して呼び出されます。定期イベントの場合、dowで指定した期間の各曜日のイベントそれぞれに呼び出されることに注意してください。

2. イベントが非表示にならない、または一時的に表示されてしまう

問題: info.el.style.display = 'none'; と設定してもイベントが完全に消えない、または一瞬表示されてから消える。 解決策: * FullCalendarの内部CSSやテーマが優先されている可能性があります。!important を使ってみるか、より具体的なCSSセレクタでdisplay: none;を適用することを検討します。ただし、!importantの使用は最後の手段にすべきです。 * 最も確実なのは、イベント要素にクラスを追加し、そのクラスにdisplay: none;を設定する方法です。 javascript // JavaScript if (datesToHide.includes(eventDate)) { info.el.classList.add('hidden-event'); } css /* CSS */ .hidden-event { display: none !important; /* 必要に応じて */ } これにより、FullCalendarの内部スタイルよりも優先して表示を制御できます。 * また、FullCalendarのイベント描画は非同期で行われることもあります。eventDidMountは描画後に呼び出されるため、瞬時の表示を防ぐには、データロード時にdisplay: 'none'を設定するなどのアプローチも検討できますが、eventDidMountでの処理が最もシンプルで効果的です。

3. 日付の比較がうまくいかない

問題: info.event.startがJavaScriptのDateオブジェクトであり、文字列や別のDateオブジェクトとの比較が正確に行えない。 解決策: * 日付を比較する際は、必ず同じ形式(例: YYYY-MM-DD文字列)に変換してから比較しましょう。FullCalendar.formatDateは非常に便利です。 javascript const eventDate = FullCalendar.formatDate(info.event.start, { year: 'numeric', month: '2-digit', day: '2-digit' }).replace(/\//g, '-'); // YYYY-MM-DD 形式に整形 この方法を使えば、タイムゾーンや時間部分の影響を受けずに日付部分のみを正確に比較できます。

解決策

上記のハマった点を踏まえ、eventDidMountを利用したイベントの非表示化は、以下のポイントを押さえることで確実に行えます。

  1. イベントの識別: events配列の各イベント定義に一意なidプロパティを付与し、eventDidMount内でそのidを使って非表示対象のイベントを特定します。これにより、意図しないイベントが非表示になるのを防ぎます。
  2. 正確な日付比較: FullCalendar.formatDate関数を使用してイベントの開始日をYYYY-MM-DD形式の文字列に変換し、非表示対象の日付リストも同じ形式で管理することで、正確な日付比較を実現します。
  3. CSSによる非表示: info.el.classList.add('hidden-event'); でイベント要素に特定のクラスを付与し、そのクラスに対してCSSで display: none !important; を設定することで、FullCalendarのデフォルトスタイルに上書きされてしまうのを防ぎ、確実に非表示にします。

このアプローチにより、dowによって定義された定期イベントのうち、特定の条件を満たすインスタンスのみを柔軟に制御し、カレンダー表示の利便性を向上させることができます。

まとめ

本記事では、FullCalendarにおける定期イベントのdowプロパティを活用しつつ、特定の日付に合致するイベントインスタンスを非表示にする方法について解説しました。

  • 要点1: FullCalendarのdowプロパティは、曜日指定の繰り返しイベントを簡単に設定できる強力な機能です。
  • 要点2: 特定の条件でdowイベントの一部を非表示にするには、eventDidMountコールバックを利用してイベントがレンダリングされた直後にDOMを操作するのが効果的です。
  • 要点3: 正確なイベント特定(idによるフィルタリング)と正確な日付比較(FullCalendar.formatDateによる整形)、そしてCSSクラスを使った確実な非表示化が実装の鍵となります。

この記事を通して、皆さんがFullCalendarを使ったカレンダー実装において、より柔軟でユーザーフレンドリーな表示を実現できるようになったことでしょう。今後は、APIから動的に非表示リストを取得する方法や、イベントのスタイルを条件に応じて変更する方法など、発展的な内容についても応用が可能です。

参考資料