先來想一下我們要做什麼事情
中間這邊可以重複使用我們拿來新增文章的 Form LiveComponent
我們新增的時候是用 %Post{} 來轉成 changeset
修改的話改成拉出來的文章 來轉成 changeset
在文章列表後面的按鈕幫編輯加上 phx-clicklib/blog_web/live/post_live/index.ex
def post_row(assigns) do
~H"""
<tr>
<td><%= @post.title %></td>
<td><%= String.slice(@post.body, 0..25) <> "..." %></td>
<td>
<a>閱讀</a>
<a phx-click="edit" phx-value-id={@post.id}>編輯</a>
<a phx-click="delete" phx-value-id={@post.id}>刪除</a>
</td>
</tr>
"""
end
這邊非常類似,我們用拿到的 id 拿到 post 後放進 assigns, 記得也要讓 form 變成 true 顯示 LiveComponent
def handle_event("edit", %{"id" => id}, socket) do
{:noreply, assign(socket, %{form: true, post: Posts.get_post(id)})}
end
原本 new 的 post 是在 LiveComponent 的初始階段 update 方法裡面直接給的,
但我們現在可以統一改由這邊給,這樣那邊就可以直接用,會單純一些。
也把原本的動作名稱改成與 edit 對應的 new ,記得按鈕要改,這邊就不贅述了。
def handle_event("new", _params, socket) do
{:noreply, assign(socket, %{form: true, post: %Posts.Post{}})}
end
這邊我們要增加一個 post={@post} 讓他把 post 的值傳進去
<%= if @form do %>
<.live_component module={BlogWeb.PostLive.Form} id="modal" post={@post} />
<% end %>
輪到 BlogWeb.PostLive.Form 了
在這邊,因為我們 new 與 edit 使用 呼叫這個 LiveComponent 的方式統一了,
便可以直接在變數裡面 matching post 出來用
lib/blog_web/live/post_live/form.ex
def update(%{post: post}, socket) do
changeset = Posts.change_post(post)
{:ok, assign(socket, %{post: post, changeset: changeset})}
end
表格本身完全不用修改就可以使用了
唯一要弄的只有判斷表格送出的時候是新增還是修改
我們可以在接收送出表格的時候檢查一下當初傳進來的 post 是新的還是舊的,可以看看 id 有沒有值,有的話就是之前存到資料庫產生的,就是舊的要更新資料
雖然 LiveView 版的頁面產生器(後面說明) 是在 router 層面就用不同的 live_action 把他分開,
而我實際上工作寫的表格也都是類似的樣子,不過其實 LiveView 非常彈性,可以依照所需調整,
我這邊就偷懶一點直接檢查 id
def handle_event("submit", %{"post" => attrs}, socket) do
result =
# 先檢查當初傳進來的 post 有沒有 id
if socket.assigns.post.id do
# 有的話就執行更新
Posts.update_post(socket.assigns.post, attrs)
else
# 不然就新增
Posts.create_post(attrs)
end
# 接著就可以拿到儲存的結果 result 來看看有沒有存成功
socket =
case result do
{:ok, _post} ->
# 有的話就回傳準備重新整理 index 頁面的 socket
push_patch(socket, to: Routes.post_index_path(socket, :index))
{:error, changeset} ->
# 沒有的話就還是同一頁,更新一下 changeset 看看錯哪邊
assign(socket, %{changeset: changeset})
end
{:noreply, socket}
end
這個就交給你做啦
這邊可以往兩個方向做,
第一個是點閱讀會連結到閱讀專用的 show 頁面,模組可能叫 BlogWeb.PostLive.Show
或是跟表格一樣打開一個 modal 來顯示內容,因為沒有複雜的互動,所以可以是單純的 Component 就好