Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
Help us understand the problem. What is going on with this article?

[Rails]FullCalenderでカレンダー機能の実装

More than 1 year has passed since last update.

実装すること

①マイページで予定管理ができるようにする
②日付をクリックで予定の作成・編集をできるようにする
※Userモデル等は作成した前提で進めていきます。

FullCalenderとは

オープンソースのカスタマイズ可能なjqueryのカレンダーライブラリです。
上手く活用することで、カレンダーのスクラッチ開発をせずにリッチなカレンダーを表示できます。

ER図

calenderER図.png

モデルの作成

$ rails g model Event title:string body:text disp_flg:boolean start:datetime end:datetime allDay:string

アソシエーションの確認

app/models/user.rb
class User < ApplicationRecord

    has_many :events

end
app/models/event.rb
class Event < ApplicationRecord

    belongs_to :user

end

ダウンロード

FullCalenderの公式ドキュメントからダウンロードし、zipを解凍します。
https://fullcalendar.io/

Gemの追加

Gemfile.
gem 'jquery-rails', '4.3.3'
gem 'fullcalendar-rails'
gem 'momentjs-rails'
$ bundle inatall

読み込み

application.htmlのhead内で読み込みます。

app/views/layouts/application.html
<head>
~
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/fullcalendar/4.2.0/core/main.min.css">
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/fullcalendar/4.2.0/daygrid/main.min.css">
~
</head>
app/assets/javascripts/application.js
//= require jquery
//= require moment
//= require fullcalendar

表示する(マイページ)

カレンダー.png

カレンダー登録.png

コントローラー

app/contorollers/users_contoroller.rb
  def show
    @user = User.find(params[:id])
    @events = Event.where(user_id: @user.id)
    @event = Event.new
  end
app/controllers/events_controller.rb
    def create
        event = Event.new(event_params)
        event.save!
        @events = Event.where(user_id: current_user.id)
    end

    def update
        event = Event.find(params[:id])
        @events = Event.where(user_id: current_user.id)
        event.update(event_params)
    end

    def destroy
        @user = User.find(params[:id])
        event = Event.find(params[:id])
        event.destroy
        redirect_to user_path(@user)
    end

    private
    def event_params
        params.require(:event).permit(:title, :start, :end, :user_id, :body)
    end

ビュー

予定を表示する・作成する

<div id="calendar"></div>でカレンダーを表示しています。
・予定を編集するときのモーダル内容はパーシャルにします。

app/views/users/show.html
<h3 class="text-center">カレンダー</h3>
<!-- カレンダーの表示 -->
<div id="calendar"></div>
<!-- もしユーザーがログインしていたら -->
<% if user_signed_in? %>
    <!-- ページのparams.idがログインユーザー.idと同じなら -->
    <% if @user.id == current_user.id %>
        <div id="inputScheduleForm" class="modal fade" tabindex="-1">
            <div class="modal-dialog modal-nm">
                <div class="modal-content">
                    <div class="modal-header">
                        <h4 class="modal-title">スケジュール登録</h4>
                    </div>
                    <div class="modal-body">
                        <%= form_with model: @event, url: events_path do |f| %>
                            <div  class="col">
                                    <p>
                                        <span>タイトル</span>
                                        <span><%= f.text_field :title, class: "form-control", placeholder: "タイトルを入力してください" %></span>
                                    </p>
                                    <span>開始日時</span>
                                    <span><%= f.datetime_field  :start, placeholder: "XXXX-XX-XX", class:"field" %> ~ </span><br>
                                    <span>終了日時</span>
                                    <span><%= f.datetime_field :end, placeholder: "XXXX-XX-XX", class:"field" %></span><br>
                                    <span>詳細
                                    <%= f.text_field :body, class: "form-control", placeholder: "タイトルの詳細を記入してください" %></span>
                            </div>
                            <div class="modal-footer">
                                <%= f.submit "登録する", class: "btn btn-primary" %>
                                <%= f.hidden_field :user_id, :value => current_user.id %>
                                <button type="button" class="btn btn-default" data-dismiss="modal">閉じる</button>
                            </div>
                        <% end %>
                    </div>
                </div>
            </div>
        </div>
<!-- 編集 ------------------------------------------------------------------>
        <div id="inputEditForm">
            <%= render 'events/edit', events: @events %>
        </div>
    <% end %>
<% end %>
    <script>
    // CRUDを行う際にCSRF対策のtokenを発行
        $(document).ready(function() {
        var prepare = function(options, originalOptions, jqXHR) {
          var token;
          if (!options.crossDomain) {
            token = $('meta[name="csrf-token"]').attr('content');
            if (token) {
              return jqXHR.setRequestHeader('X-CSRF-Token', token);
            }
          }
        };
        }
        )

        // カレンダー表示
        $('#calendar').fullCalendar ({
            header: {
                left: 'prev,next today',
                center: 'month,agendaWeek,agendaDay',
                right: 'title'
            },

            buttonText: {
                  prev: "<",
                  next: ">"
            },

            timezone: 'UTC',
            events: '/users/events.json',
            navLinks: true,
            selectable: true,
            selectHelper: true,
            // 日付クリック
            dayClick : function ( date , jsEvent , view ) {
                $('#inputScheduleForm').modal('show');
                },

            // event クリックで編集、削除
            eventClick : function(event, jsEvent , view) {
                jsEvent.preventDefault();
                $(`#inputScheduleEditForm${event.id}`).modal('show');
            },

            eventMouseover : function(event, jsEvent , view) {
                jsEvent.preventDefault();
            }
        })

    </script>

app/views/events/create.js
//フォームを空にする
$('input[type="text"]').val('');
//モーダルを消す
$('#inputScheduleForm').modal('hide');
//作成した予定を差し替える
$('#inputEditForm').html('<%= escape_javascript(render("events/edit", events: @events )) %>');
// フルカレンダー を一度消しもう一度表示
$('#calendar').fullCalendar('refetchEvents')

予定を編集する

app/views/events/_edit.html
<% events.each do |event| %>
    <div id='inputScheduleEditForm<%= event.id %>' class="modal fade" tabindex="-1">
        <div class="modal-dialog modal-nm">
            <div class="modal-content">
                <div class="modal-header">
                    <h4 class="modal-title">スケジュール編集</h4>
                </div>
                <div class="modal-body">
                    <div  class="col">
                        <%= form_with(model: event, url: users_event_path(event), method: :put) do |f| %>
                            <p>
                                <span>タイトル</span>
                                <span id="inputTitle" value=""><%= f.text_field :title, class: "form-control", placeholder: "タイトルを入力してください" %></span>
                            </p>
                            <span>開始日時</span>
                            <span><%= f.datetime_field  :start, placeholder: "XXXX-XX-XX", class:"field" %> ~ </span><br>
                            <span>終了日時</span>
                            <span><%= f.datetime_field  :end, placeholder: "XXXX-XX-XX", class:"field" %></span>
                            <span><br>
                                詳細
                                <%= f.text_field :body, class: "form-control", placeholder: "タイトルの詳細を記入してください" %>
                            </span>
                            <div class="modal-footer">
                                <%= f.hidden_field :user_id, :value => current_user.id %>
                                <%= f.submit "編集する", class: "btn btn-primary" %>
                                <button type="button" class="btn btn-default" data-dismiss="modal">閉じる</button>
                            </div>
                        <% end %>
                    </div>
                </div>
            </div>
        </div>
    </div>
<% end %>
app/views/events/update.js
//updateした内容を差し替え
$('#inputEditForm').html('<%= escape_javascript(render("events/edit", events: @events)) %>');
//モーダル背景画面を消す
$('.modal-backdrop').remove();
// フルカレンダー を一度消しもう一度表示
$('#calendar').fullCalendar('refetchEvents')

最後に

最後までご覧いただきありがとうございます。
初学者ですので間違っていたり、分かりづらい部分もあるかと思います。
何かお気付きの点がございましたら、お気軽にコメントいただけると幸いです。

twitter:https://twitter.com/yto_oct
note:https://note.com/yto_oty

参考

公式ドキュメント
https://fullcalendar.io/
[Rails]FullcalendarのイベントをDBに保存・編集
https://qiita.com/ShoutaWATANABE/items/3d0cddafadb4f275991e

yuto_1014
ご覧いただきありがとうござます! ≪営業→→Javaエンジニア≫ Ruby,Rails,Java,Spring,cubby,PostgreSQL,MySQL
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away