📆
Phoenix LiveViewによるDate Picker UIの実装
この記事について
2024年3月15日に東京浜松町・大門でElixir/Phoenix 勉強会+採用事例紹介と題するオフラインイベントが開催されました。
この記事は、私(黒田)が行った発表「Phoenix LiveView講座(20分)」の題材である DaimonDataPicker の実装手順を解説したものです。
開発環境
- Elixir 1.16.1
- Phoenix 1.7.11
骨格の作成
mix phx.new --no-ecto --no-dashboard --no-mailer daimon_date_picker
cd daimon_date_picker
-
ebd15a6
mix phx.new --no-ecto --no-dashboard --no-mailer daimon_date_picker
準備作業
README.md
を作成し、コントローラ関連のファイル群を削除。
Phoenix LiveViewで空白ページを表示
lib/daimon_date_picker_web/live
ディレクトリを作成し、そこに home_live.ex
を作成。中身は次の通り:
defmodule DaimonDatePickerWeb.HomeLive do
use Phoenix.LiveView
def mount(_params, _session, socket) do
{:ok, socket, layout: {DaimonDatePickerWeb.Layouts, :app}}
end
end
また、同じディレクトリに home_live.html.heex
を作成:
<div>home_live.html.heex</div>
-
dcdf7e3
Create DaimonDatePicker.HomeLive and an empty heex template
-
48e77a8
Apply :app layout to the home page
Date Picker UIの実装①
日付入力欄を設置し、その内部をクリックすると、Date Pickerというテキストの表示・非表示が切り替わるところまで実装。
-
159a710
Show text input with today's date as the initial value
-
a6f815e
Impl. toggle_date_picker event handler
Date Picker UIの実装②
Date Picker UIのビジュアルデザインが完成。
-
c85e100
Show current month and prev/next buttons
-
5db49de
Show week days
-
a5ee92f
Show all days for the current month
Date Picker UIの実装③
Prevボタン、Nextボタンで socket.assigns.current_month
の値を切り替えるところまで実装。
def handle_event("prev_month", _params, socket) do
prev_month =
socket.assigns.current_month
|> Date.add(-1)
|> Date.beginning_of_month()
socket = assign(socket, :current_month, prev_month)
{:noreply, socket}
end
def handle_event("next_month", _params, socket) do
next_month =
socket.assigns.current_month
|> Date.end_of_month()
|> Date.add(1)
socket = assign(socket, :current_month, next_month)
{:noreply, socket}
end
Dateモジュールの関数群を活用して前月あるいは翌月の初日を作り、socket.assigns.current_month
にセットしている。
-
9934f48
Impl. prev_month and next_month event handlers
Date Picker UIの実装④
カレンダー内の日付がクリックされると、socket.assigns.selected_date
に日付がセットされるところまで実装。
def handle_event("select_date", %{"day" => day} = _params, socket) do
eom = Date.end_of_month(socket.assigns.current_month)
selected_date =
case Integer.parse(day) do
{d, ""} when d in 1..eom.day ->
%{socket.assigns.current_month | day: d}
_ ->
socket.assigns.current_month
end
socket =
socket
|> assign(:selected_date, selected_date)
|> assign(:activated, false)
{:noreply, socket}
end
文字列として送られてくる "day"
パラメータの値を Integer.parse/2 で整数に変換し、それを socket.assigns.current_month
の day
フィールドにセットしている。"day"
パラメータは外部から送られてくる値であるため、その月の日付として正しいことを念のため確認している。
-
2e175ac
Impl. select_date event handler
Discussion