iT邦幫忙

2022 iThome 鐵人賽

DAY 26
0
Modern Web

速成 Phoenix, 2022年最受喜愛框架系列 第 26

{26, LiveView, "共用 Component"}

  • 分享至 

  • xImage
  •  

我們還缺 修改功能

先來想一下我們要做什麼事情

  1. 點擊編輯發出 編輯事件,附上要編輯的文章 id
  2. 接收編輯事件,拉出要編輯的文章
  3. 打開 Form LiveComponent 並給入 要編輯的文章
  4. 填完表格送出更新
  5. 重新整裡列表

中間這邊可以重複使用我們拿來新增文章的 Form LiveComponent
我們新增的時候是用 %Post{} 來轉成 changeset
修改的話改成拉出來的文章 來轉成 changeset

編輯按鈕

在文章列表後面的按鈕幫編輯加上 phx-click
lib/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

更改傳進 Component 的數值

這邊我們要增加一個 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 就好


上一篇
{25, LiveView, "LiveView 事件"}
下一篇
{27, LiveView, "聊天室介面"}
系列文
速成 Phoenix, 2022年最受喜愛框架30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言