LoginSignup
9
3

More than 3 years have passed since last update.

Laravel+jQuery+fullCalendarで予定を非同期で登録する

Last updated at Posted at 2020-12-04

先日投稿した記事と被っている箇所がありますがあしからず。

【技術スタック】
- Laravel 6.0
- AdminLTE 3 (ComposerでLaravelにインストール)
- jQuery 3.3.1+ (AdminLTEにデフォルトで入っている)
- FullCalendar 5.3.2 (AdminLTEでデフォルトで入ってるのは古いので別途新しいバージョンをCDNで導入)

FullCalendar概要

オープンソースのカスタマイズ可能なjQueryのカレンダーライブラリ。

公式ドキュメント:https://fullcalendar.io/docs

※FullCalenderのバージョンによってFullCalendarのコードの書き方がかなり変わるようなので、注意が必要です。
ver.3まではjQueryの記述方法でカレンダーを描画していましたが、ver.4以降は生のjavascriptでの記述方法に変わりました。

  • DOMの取得方法がネイティブのgetElementByIdになった
  • カレンダーの生成方法が new FullCalendar.Calendar() になった

JavaScript カレンダープラグイン FullCalendar ~その1 スケジュール表を作成する~ | 打ち聞かせ 様より引用

全体の大まかな流れ

  1. モデル、テーブル作成しておく(FullCalendarのイベントに対応するカラム名にする)
  2. フォームに情報を入力してボタンをクリックすると、jQuery側でクリックを検知&フォームの情報を取得
  3. Ajaxを使い、2で取得した情報をPOSTでコントローラー側に送信
  4. コントローラー側で送信された情報をsave

基本の書き方が下記。


var calendar = new Calendar(calendarEl, {
  timeZone: 'UTC',
  events: [
    {
      id: 'a',
      title: 'testEvent',
      start: '2020-11-01'
    }
  ]
})

https://fullcalendar.io/docs/event-parsing に記載のイベントオブジェクト一覧で、全てのイベントに関連するプロパティを見ることができます。
下記一部抜粋です。

プロパティ名 概要
id 文字列または整数。イベントを一意に識別します。getEventByIdに便利です。
start
イベントの開始時刻。イベントが明示的に allDay である場合、時、分、秒、ミリ秒は無視されます。
title
イベントに表示されるテキスト。
color
backgroundColorとborderColorを同時に指定するためのエイリアス。

上記の記述方法だと、 「testEventというイベント名が2020/11/1の日付に表示」されます。
今回は、 events の中身を、DBの値に置き換えていきたいと思います。

1. モデル、テーブル作成しておく(FullCalendarのeventプロパティに対応するカラム名にする)

$ php artisan make:model Event -m

で、モデル作成&マイグレーションファイルを作成します。
マイグレーションファイルを下記のように編集


// create_events_table.php
    public function up()
    {
        Schema::create('events', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->timestamps();
            $table->date('start');
            $table->date('end')->nullable();
            $table->string('title');
            $table->string('color')->nullable();
        });
    }
$ php artisan migrate

でマイグレーションをかけてeventsテーブルを作成します。

2. フォームに情報を入力してボタンをクリックすると、jQuery側でクリックを検知&フォームの情報を取得

// test.blade.php
<div style="margin-top:30px; border:1px solid gray;">
  <form id="form" action="">
    <p><input type="text" name="title" placeholder="タイトル入力"></p>
    <p><input type="date" name="start" placeholder="日付入力"></p>
    <p><input type="color" name="color" ></p>
  </form>

  <button id="bt2">
    Ajax->DBにPostテスト
  </button>

CSSはガン無視です(笑)
inputタグのname属性に、送信したい値のキーを書いてあげるのがポイントです。

// scriptタグの中
$("#bt2").click(function () { // bt2のidの要素をクリックしたときに発動
  $.ajaxSetup({
    headers: {
      "X-CSRF-TOKEN": $('meta[name="csrf-token"]').attr("content"),
    },
  });
  var formData = $("#form").serialize(); 

  // ajax部分は後に記述 //
});

  $.ajaxSetup({
    headers: {
      "X-CSRF-TOKEN": $('meta[name="csrf-token"]').attr("content"),
    },
  });

はおまじないです。これを設定することによって、セキュアなAjax通信を行うことができます。

var formData = $("#form").serialize();では、フォーム要素を取得して、name属性とvalue属性をキーとvalueの形式に変換します。
jQuery serializeでキーバリューにするサンプル | ITSakura 様を参照

3. Ajaxを使い、2で取得した情報をPOSTでコントローラー側に送信


$("#bt2").click(function () {
  $.ajaxSetup({
    headers: {
      "X-CSRF-TOKEN": $('meta[name="csrf-token"]').attr("content"),
    },
  });
  var formData = $("#form").serialize();
  console.log(formData);

  $.ajax({
    //POST通信
    type: "post", //HTTP通信のメソッドをPOSTで指定
    //ここでデータの送信先URLを指定します。
    url: "/postevent", //通信先のURL
    dataType: "json", // データタイプをjsonで指定
    data: formData, // serializeしたデータを指定
  })
    //通信が成功したとき
    .then((res) => {
      console.log(res);
      // カレンダーの再描画
      var calendarEl = document.getElementById("calendar");
      var calendar = new FullCalendar.Calendar(calendarEl, {
        headerToolbar: {
          left: "prev,next today",
          center: "title",
          right: "dayGridMonth,timeGridWeek,timeGridDay,listWeek",
        },
        locale: "ja",
        editable: true,
        googleCalendarApiKey: "GoogleのAPIKEY",
        eventSources: [
          {
            googleCalendarId: "japanese__ja@holiday.calendar.google.com", //祝日の予定を取得
            rendering: "background",
            color: "#FF6666",
          },
        ],
        events: "/getevents",
        selectable: true,
      });
      calendar.render(); //カレンダーを再描画
    })
    //通信が失敗したとき
    .fail((error) => {
      console.log(error.statusText);
    });
});

4. コントローラー側で送信された情報をsave

//web.php
Route::post('/postevent', '****Controller@postEvent'); //任意のコントローラー名を記述
// コントローラー側
  public function postEvent(Request $request)
  {
    $event = new Event();
    $event->start = $request->start; 
    $event->title = $request->title;
    $event->color = $request->color;


    $event->save();
    return $event;
  }

これで下記のような形になりました。
Postテストを押すと・・・
image.png

ページリロード無しでカレンダーだけが再描画されます。
image.png

DBにもリアルタイムに画像が保存されていました。
image.png

9
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
3