[Rails] StimulusJSとTOAST UIでカレンダーを表示してみる

2024/01/17

Rails
StimulusJS
TOAST UI

こんにちは。

今回は、RailsでStimulusJSとTOAST UIを使ってカレンダーを表示してみます。

StimulusJSとは

StimulusJSは、HotwireのJavaScriptフレームワークです。

HTMLのdata属性を使って、JavaScriptを管理するのでコードがシンプルかつ軽量になります。

Rails7.0からは、デフォルトでStimulusJSが導入されています。

参考: https://stimulus.hotwired.dev/

TOAST UIとは

TOAST UIは、韓国のNHN社が開発しているオープンソースのJavaScriptライブラリです。

TOAST UIは、様々な種類のUIコンポーネントを提供しています。

今回は、TOAST UIのカレンダーを使ってみます。

参考: https://ui.toast.com/

実装

今回は、StimulusJSが使える前提での実装になります。

セットアップ

まずは、TOAST UIのカレンダーを使えるようにします。

./bin/importmap pin @toast-ui/calendar

上記コマンドで、config/importmap.rbに以下が追加されます。

config/importmap.rb
pin "@toast-ui/calendar", to: "https://ga.jspm.io/npm:@toast-ui/calendar@2.1.3/dist/toastui-calendar.mjs"
pin "tui-date-picker", to: "https://ga.jspm.io/npm:tui-date-picker@4.3.3/dist/tui-date-picker.js"
pin "tui-time-picker", to: "https://ga.jspm.io/npm:tui-time-picker@2.1.6/dist/tui-time-picker.js"

CSSも読み込むために、app/views/layouts/application.html.hamlに以下を追加します。

app/views/layouts/application.html.haml
%link{href: "https://uicdn.toast.com/calendar/latest/toastui-calendar.min.css", rel: "stylesheet"}/

上記はHTMLのhead内に追加してください。

StimulusJSのコントローラーを作成する

次に、StimulusJSのコントローラーを作成します。

import { Controller } from "@hotwired/stimulus";
import Calendar from "@toast-ui/calendar";

export default class extends Controller {
  static targets = ["calendar"]
  static values = { events: Array }

  connect() {
    this.calendar = new Calendar(this.calendarTarget, {
      defaultView: 'month',
      isReadOnly: true,
      scheduleView: true,
      template: {
        time(event) {
          const { start, title } = event;
          const date = new Date(start);
          const hour = date.getHours().toString().padStart(2, '0');
          const minute = date.getMinutes().toString().padStart(2, '0');
          const time = `${hour}:${minute}`;

          return `<span>${time} ${title}</span>`;
        },
        allday(event) {
          return `<span style="color: gray;">${event.title}</span>`;
        },
      },
      useDetailPopup: true,
    });
    this.eventsValue.forEach((event) => {
      this.calendar.createEvents([
        {
          id: event.id,
          calendarId: '1',
          title: event.title,
          category: 'time',
          dueDateClass: '',
          start: event.start,
          end: event.end,
        },
      ]);
    });
  }

  next() {
    this.calendar.next();
  }

  prev() {
    this.calendar.prev();
  }
}

上記のコントローラーでは、以下のことを行っています。

  • calendarTargetにカレンダーを表示する
  • eventsValueに入っているイベントをカレンダーに表示する
  • 翌月に移動するnextメソッドを定義する
  • 前月に移動するprevメソッドを定義する

eventsValueは、以下の形式を想定しています。
こちらは後ほど、Railsのコントローラーから渡すようにします。

[
  {
    id: 1,
    title: 'イベント1',
    start: '2021-01-01T00:00:00+09:00',
    end: '2021-01-01T00:00:00+09:00',
  },
  {
    id: 2,
    title: 'イベント2',
    start: '2021-01-02T00:00:00+09:00',
    end: '2021-01-02T00:00:00+09:00',
  },
]

Viewを作成する

次に、Viewを作成します。

app/views/calendars/show.html.haml
.h-screen{ data: {controller: 'calendar', 'calendar-events-value' => @events.to_json}}
  .p-4.flex.justify-between
    %button.p-2.rounded-full.bg-blue-500.text-white{ class: 'hover:bg-blue-600', data: {action: 'click->calendar#prev'}}
      %svg.w-6.h-6{:fill => "none", :stroke => "currentColor", "stroke-width" => "1.5", :viewbox => "0 0 24 24", :xmlns => "http://www.w3.org/2000/svg"}
        = render 'svgs/chevron_left'
    %button.p-2.rounded-full.bg-blue-500.text-white{ class: 'hover:bg-blue-600', data: {action: 'click->calendar#next'}}
      %svg.w-6.h-6{:fill => "none", :stroke => "currentColor", "stroke-width" => "1.5", :viewbox => "0 0 24 24", :xmlns => "http://www.w3.org/2000/svg"}
        = render 'svgs/chevron_right'
  .h-full{ data: {'calendar-target' => 'calendar'}}

上記のコードでは、以下のことを行っています。

  • Stimulusのcalendarコントローラーを呼び出す
  • カレンダーに表示するイベントを渡す
  • カレンダーの前月に移動するprevメソッドを呼び出すボタンを作成する
  • カレンダーの翌月に移動するnextメソッドを呼び出すボタンを作成する
  • カレンダーを表示する

Railsのコントローラーを作成する

最後に、Railsのコントローラーを作成します。

app/controllers/calendars_controller.rb
class CalendarsController < ApplicationController
  def show
    @events = [
      {
        id: 1,
        title: 'イベント1',
        start: '2021-01-01T00:00:00+09:00',
        end: '2021-01-01T00:00:00+09:00',
      },
      {
        id: 2,
        title: 'イベント2',
        start: '2021-01-02T00:00:00+09:00',
        end: '2021-01-02T00:00:00+09:00',
      },
    ]
  end
end

上記のコードでは、カレンダーに表示するイベントを定義しています。
ここをデータベースから取得するようにすれば、データベースに保存されているイベントをカレンダーに表示することができます。

動作確認

こんな感じのカレンダーが表示されれば成功です。
(イベントは都合上表示させていませんが、イベントも表示されます。)

カレンダー

まとめ

今回は、RailsでStimulusJSとTOAST UIを使ってカレンダーを表示してみました。

StimulusJSは外部のライブラリとも相性が良く、簡単に導入することができますね。

個人的にはnode_modulesがないことでもすごく便利に感じています。

今回はこのあたりで。

Related Posts

[Rails 7.0] Stimulusのコントローラーとりあえず作っとけ5選を公開します

[Rails 7.0] Stimulusのコントローラーとりあえず作っとけ5選を公開します

RailsでLIFFアプリを作る

RailsでLIFFアプリを作る