這個章節我們要把原本使用 Controller-View 的感激筆記頁面一步一步的改成 LiveView 版本,並加上一些新功能。
通常 LiveView 也是使用 RESTful 風格的路徑設定,所以通常在這邊的 note index 頁面會一樣用 /notes
,但是在這篇教學一方面是想保留原本的 Controller-View 版本,另一方面是這個站的主要功能只有感激筆記,所以在這邊用 /
來取代 /notes
,之後加上的新增頁面也會依照這個模式改為 /new
。
scope "/", GratitudeWeb do
pipe_through :browser
# 將原本的首頁用我們即將建立的 Index 取代
live "/", NoteLive.Index, :index
# 舊的 Controller-View 版本
resources "/notes", NoteController, except: [:show]
live "/demo", DemoLive
end
路徑設定好後在 lib/gratitude_web/live/note_live/index.ex
建立一個 NoteLive.Index LiveView module
defmodule GratitudeWeb.NoteLive.Index do
use GratitudeWeb, :live_view
alias Gratitude.Notes
def mount(params, session, socket) do
notes = Notes.list_notes()
{:ok, assign(socket, notes: notes)}
end
def render(assigns) do
~H"""
<.header>感激筆記 LiveView 版</.header>
<.table id="notes" rows={@notes}>
<:col :let={note} label="ID"><%= note.id %></:col>
<:col :let={note} label="內容"><%= note.content %></:col>
</.table>
"""
end
end
可以注意到跟上一個 LiveView 頁面 DemoLive
相比,我們使用NoteLive.Index
來作為模組名稱,且檔案的位置也是 lib/gratitude_web/live/note_live/index.ex
,雖然這次的範例只會有一個 LiveView 頁面,但是如果有多個頁面的話,可以把相關的頁面與共用 component 放在同一個資料夾下,如果有顯示單個 note 的頁面需求,就會有另一個 NoteLive.Show
的模組,並且放在 lib/gratitude_web/live/note_live/show.ex
。
在 DemoLive
的 live 函式沒有像這次的 NoteLive.Index
一樣後面多加一個參數 :index
,
我們先來看看 live
函式的定義
live(path, live_view, action \\ nil, opts \\ [])
在 DemoLive
的時候,我們忽略了第三個 action
讓它使用預設值 nil
,由於我們的 DemoLive
功能相當少所以不需要為他特別指定 action
。
如果有多個路徑要用同一個 LiveView 通常會用 action
來區分,
例如之後我們會需要新增 note 的路徑 (/new
),又想要用同一個 LiveView 來處理的話,就會在 Router 裡面使用 action 來區分:
live "/", NoteLive.Index, :index
live "/new", NoteLive.Index, :new
這樣一來,在 LiveView Module 裡我們可以在 assigns map 使用 live_action
得到該值,例如:
def mount(params, session, socket) do
case socket.assigns.live_action do
:index -> # 如果是 index 頁面要做的事
:new -> # 如果是 new 頁面要做的事
end
{:ok, socket}
end
或是在 heex template 上判斷依照不同的 action 來顯示不同的內容:
<.header>
<%= if @live_action == :index do %>
列出所有的感激筆記
<% else %>
新增感激筆記
<% end %>
</.header>