【Laravel】FullCalendarでカレンダーを導入しよう!

2021年9月13日

カレンダーは予約システムなどよくシステムでも見かけます。しかし、0から作ろうとすると結構大変です。そこでおすすめしたいのがJavaScriptのFullCalendarというライブラリです。

当記事ではLaravelプロジェクトにFullCalendarライブラリを導入しアレンジしてみます!

初心者におすすめ動画

FullCalendarを初めて導入される方やFullCalendarでどんな事ができるのかを知りたいという方向けにはUdemyの講座がおすすめです。

「LaravelとFullCalendarでスケジュールカレンダーアプリをつくろう!」

記事情報

FullCalendar公式ドキュメント

バージョン
Laravel 8.60.0
FullCalendar v.5.9.0

①FullCalendarの導入

今回は公式サイトからファイルをDownloadして導入してみます。
Downloadからファイル一式をダウンロードしてください。

ダウンロードしたファイル一式をpublic配下に配置してください。

表示したいbladeファイルに以下のように記述してください。

<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">

        <title>Laravel × FullCalendar</title>

        <!-- Fonts -->
        <link href="https://fonts.googleapis.com/css2?family=Nunito:wght@400;600;700&display=swap" rel="stylesheet">
        <!-- Styles -->
        <link href="{{ asset('css/app.css') }}" rel="stylesheet">
        <!-- Script -->
        <script src="{{ asset('js/app.js') }}"></script>
    </head>
    <body>
        <div id="app">
            <div class="m-auto w-50 m-5 p-5">
                <div id='calendar'></div>
            </div>
        </div>

        <link href='{{ asset('fullcalendar-5.9.0/lib/main.css') }}' rel='stylesheet' />
        <script src='{{ asset('fullcalendar-5.9.0/lib/main.js') }}'></script>
        <script>
            document.addEventListener('DOMContentLoaded', function() {
                var calendarEl = document.getElementById('calendar');
                var calendar = new FullCalendar.Calendar(calendarEl, {
                    initialView: 'dayGridMonth'
                });
                calendar.render();
            });
        </script>
    </body>
</html>

これで導入は完了です。

②オプション設定でカレンダーをアレンジ

導入ができたので次はカレンダーの見出しをアレンジしていきます。
次のようにコードを追記してください。

<script>
    document.addEventListener('DOMContentLoaded', function() {
        var calendarEl = document.getElementById('calendar');
        var calendar = new FullCalendar.Calendar(calendarEl, {
            initialView: 'dayGridMonth',
            locale: 'ja',
            height: 'auto',
            firstDay: 1,
            headerToolbar: {
                left: "dayGridMonth,listMonth",
                center: "title",
                right: "today prev,next"
            },
            buttonText: {
                today: '今月',
                month: '月',
                list: 'リスト'
            },
            noEventsContent: 'スケジュールはありません',
         });
         calendar.render();
    });
</script>

追記したらページを更新してみて下さい。下の画像のような画面になります。

オプションについて1つ1つ解説していきます。

まず、initialViewはカレンダーの月表示や週表示を変えることができます。
ちなみにtimeGridWeekに設定すると下の画像のようになります。

localeをjaに設定すると日本語になります。
heightはカレンダーの高さを自動で調節してくれます。カレンダー内にスケジュールが入った際にテキストが長いとスクロールされるようになりますが、もしスクロールではなく高さを可変にして全表示したい場合はこちらが便利です。
firstDayは開始曜日を設定できます。0(日曜日)〜6(土曜日)で設定できます。
headerToolbarはカレンダー上部の「表示切り替え」「タイトル」「日付切り替え」などの位置や表示を設定できます。不要であれば消すこともできます。
buttonTextはボタンのテキストを設定することができます。
noEventsContentはリスト表示時にイベントが1件もないときのテキストを設定することができます。

他にもいろいろなオプションがあると思います。詳細は公式ドキュメントを確認してみてください。

次回はサーバーサイドからデータを取得してカレンダーに表示してみたいと思います。

③サーバーからイベントデータを取得してカレンダーに表示する

次にカレンダーにスケジュールを表示してみましょう。

データはAjaxでサーバー側から予定を取得します。

まずはルートを定義します。

//web.php
Route::get('get_events', [CalendarController::class, 'getEvents']);

コントローラにデータを返す処理を記述します。

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class CalendarController extends Controller
{
    public function getEvents()
    {
        return [
            [
                'title' => '美容院',
                'description' => '人気の美容室予約取れた',
                'start' => '2021-09-10',
                'end'   => '2021-09-10',
            ],
            [
                'title' => 'シルバーウィーク旅行',
                'description' => '人気の旅館の予約が取れた',
                'start' => '2021-09-20 10:00:00',
                'end'   => '2021-09-22 18:00:00',
                'url'   => 'https://admin.juno-blog.site',
            ],
            [
                'title' => '給料日',
                'start' => '2021-09-30',
                'color' => '#ff44cc',
            ],
        ];
    }
}

各イベントデータを2次元配列に格納して返します。
各イベントのキーには以下のようなデータを持たせられます。

titleカレンダーに表示するテキストです
descriptionイベントの詳細のテキストを持たせられます。
カレンダー上でイベントにカーソルを合わせるとポップアップが表示させる際に表示されます。
startイベントの開始日時
endイベントの終了日時
urlカレンダー上でイベントにリンクを貼ることができます。
colorイベントの色を変更できます。


上記以外にもあると思うので、こちらも必要に応じて公式ドキュメントで探してみてください。

実際にはデータはDBから取得したものを整形して動的に返してあげます。ここでは例として簡易的にデータを作成してみました。

では、bladeに戻ってajaxからデータを取得する処理を書いていきます。
以下のようにjsに追記してください。

<script>
    document.addEventListener('DOMContentLoaded', function() {
        var calendarEl = document.getElementById('calendar');
        var calendar = new FullCalendar.Calendar(calendarEl, {
            initialView: 'dayGridMonth',
            locale: 'ja',
            height: 'auto',
            firstDay: 1,
            headerToolbar: {
                left: "dayGridMonth,listMonth",
                center: "title",
                right: "today prev,next"
            },
            buttonText: {
                today: '今月',
                month: '月',
                list: 'リスト'
            },
            noEventsContent: '案件はありません',
            eventSources: [ // ←★追記
                {
                    url: '/get_events',
                },
            ],
            eventSourceFailure () { // ←★追記
                console.error('エラーが発生しました。');
            },
            eventMouseEnter (info) { // ←★追記
                $(info.el).popover({
                    title: info.event.title,
                    content: info.event.extendedProps.description,
                    trigger: 'hover',
                    placement: 'top',
                    container: 'body',
                    html: true
                });
            }
        });
        calendar.render();
    });
</script>

eventSourcesのurlにコントローラのパスを記述します。
これだけでカレンダーが呼び出された瞬間にデータを取ってきてくれます。簡単ですよね!

eventSourceFailureはeventSourcesでエラーになった際に実行されます。

もし、より詳細な情報を表示するためにポップアップを使用したい場合はeventMouseEnterを使用します。
イベントにカーソルを合わせるとポップアップが表示されます。

以上でサーバーからデータを取得して表示することができました!
ちなみにこのAjaxは月を変更するたびに呼び出されるため、データ総数が多い場合は注意が必要です。

④カレンダーのデザインをアレンジする

さて、ここまででカレンダーとしては機能するようになりましたが。
しかし今のままだとカレンダーとしては殺風景です。

そこで土曜日と日曜日の色を変えてみます。
色の変更はCSSで変更できます。

以下のようにスタイルを記述してください。

.fc-col-header-cell-cushion,
.fc-daygrid-day-number,
.fc-daygrid-day-top{
    color: #333;
}
.fc-day-sat{
    background-color: #cce3f6;
}
.fc-day-sun{
    background-color: #f4d0df;
}

これでリロードすると下の図のようになります。

カレンダーに適用されているclassはブラウザのDevツールから確認できるので変えたい部分のclassにスタイルをあててみてください。

まとめ

今回はLaravelのプロジェクトにカレンダーを導入してみました。
導入が簡単で機能も豊富なので、もしカレンダーを導入する際は使ってみてください。

参考動画

FullCalendarについてさらに活用方法を知りたい方は

Udemy「LaravelとFullCalendarでスケジュールカレンダーアプリをつくろう!」

もおすすめ!

上記の内容に加え、下記の内容も収録

・ドラッグ&ドロップによる移動
・カレンダー上で期間を短くしたり、長くしたりする処理