iT邦幫忙

2022 iThome 鐵人賽

DAY 24
0
Modern Web

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

{24, LiveView, "LiveView裡的表格"}

  • 分享至 

  • xImage
  •  

在 LiveView 裡面使用表格

在完成準備放新文章的 modal 後,其實就是在裡面加上 <.form > 就可以了,但是有幾個東西需要先加進 assigns 裡

更新 BlogWeb.PostLive.Form 的 update, 我們要在打開這個 LiveComponent 的時候把 changeset 加進來
lib/blog_web/live/post_live/form.ex

  def update(_assigns, socket) do
    post = %Posts.Post{}
    changeset = Posts.change_post(post)
    {:ok, assign(socket, %{post: post, changeset: changeset})}
  end

這裡與傳統的 MVC 路線類似,用 <.form > 帶入 changeset 把表格畫出來

這邊來新增一個 component 裝表格
跟傳統不同的是,LiveView 這邊使用 phx-submit 來呼叫送出事件到 LiveView,而不是重新發一個 Post 連線
我們待會可以用 handle_event 來把 submit 接起來處理表格送出。

另外在 LiveView 有 phx-change 這個 binding 可以讓我們決定表格有改動的時候我們要做什麼,通常在這邊我們拿來即時驗證表格

這邊要注意的是,因為我們這次把表格在 LiveComponent 處理,所以必須要加上 phx-target={@myself} 告訴 LiveView 這個事件是由 LiveComponent 處理,
如果沒有寫的話,會送去母層的 Index LiveView,其實要的話也是可以過去處理,但我們這次想讓表格的東西集中在一起。

  def post_form(assigns) do
    ~H"""
    <.form let={f} for={@changeset} phx-change="validate" phx-submit="submit" phx-target={@myself}>
      <%= label(f, :title) %>
      <%= text_input(f, :title) %>
      <%= error_tag(f, :title) %>

      <%= label(f, :body) %>
      <%= textarea(f, :body) %>
      <%= error_tag(f, :body) %>

      <div>
        <%= submit("送出") %>
      </div>
    </.form>
    """
  end

把新的 component 放進 modal 裡

  def render(assigns) do
    ~H"""
    <div>
      <.modal>
        <h1>新增文章</h1>
        <.post_form changeset={@changeset} myself={@myself} />
      </.modal>
    </div>
    """
  end

這樣就可以顯示表格了

https://ithelp.ithome.com.tw/upload/images/20220928/20141054jMy5NtVdsZ.png

但我們會發現輸入或是送出都會壞掉導致 LiveView 重新整理
這是因為我們還沒有寫要怎麼處理那些事件

LiveView 驗證表格

這邊做的事情其實就是把表格準備送出的內容套進 changeset 裡面,讓他檢查一下我們之前寫的規則
要記得把 changeset 的 action 改成 validate 這樣畫面上才會顯示檢查的錯誤項目

  def handle_event("validate", %{"post" => attrs}, socket) do
    changeset =
      Posts.change_post(socket.assigns.post, attrs)
      |> Map.put(:action, :validate)

    {:noreply, assign(socket, %{changeset: changeset})}
  end

https://ithelp.ithome.com.tw/upload/images/20220928/20141054KFR09BCSBq.png

就這樣我們就完成了即時的錯誤回饋,這個在以前的作法要弄是很麻煩的。

LiveView 送出表格

這裡跟我們之前在 PostController create 動作做的事情非常類似
我們使用 Posts.create_post 來建立文章

如果建立成功,我們用 push_patch 來回到 Index 頁面並重整一次 assigns
如果失敗,就把回傳的 changeset 再丟回 assigns

  def handle_event("submit", %{"post" => attrs}, socket) do
    socket =
      case Posts.create_post(attrs) do
        {:ok, _post} ->
          push_patch(socket, to: Routes.post_index_path(socket, :index))

        {:error, changeset} ->
          assign(socket, %{changeset: changeset})
      end

    {:noreply, socket}
  end

一些額外的事

如果我們使用 push_patch 來重新整理 BlogWeb.PostLive.Index 頁面的話,
因為連線不會中斷,所以他會去呼叫另一個 callback handle_params 文件

這個 handle_params 正常會在 mount 之後執行,如果沒有定義就跳過,
那如果我們剛剛直接用 push_patch 回到頁面的話,他會略過 mount 直接找 handle_params

所以我們要調整一下 BlogWeb.PostLive.Index

  def mount(_params, _session, socket) do
    {:ok, socket}
  end

  def handle_params(_params, _uri, socket) do
    {:noreply, assign(socket, %{posts: Posts.list_posts(), form: false})}
  end

好了之後我們整個循環就完成了


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

尚未有邦友留言

立即登入留言