You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Elixir LiveView表单提交后无法重置问题求助

问题:Phoenix LiveView表单提交成功后无法清空

表单可正常提交并创建Gist(数据能持久化到PostgreSQL数据库),缺失字段时也会触发验证错误,但成功提交后无法清空表单。尝试过创建空白Gist Changeset并重新赋值给form,但并未生效。


代码文件:create_gist_live.ex

defmodule ElixirGistWeb.CreateGistLive do
  use ElixirGistWeb, :live_view
  import Phoenix.HTML.Form
  alias ElixirGist.{Gists, Gists.Gist}

  def mount(_params, _session, socket) do
    socket =
      assign(
        socket,
        form: to_form(Gists.change_gist(%Gist{}))
      )

    {:ok, socket}
  end

  def handle_event("create", params, socket) do
    case Gists.create_gist(socket.assigns.current_user, params["gist"]) do #passing params["gist"] is so so necessary. I was stuck for a day just passing params at first
      {:ok, _gist} ->
        changeset = Gists.change_gist(%Gist{})
        socket =
          socket
          |> put_flash(:info, "Gist created successfully.")
          |> assign(:form, to_form(changeset))
        {:noreply, socket}
      {:error, %Ecto.Changeset{} = changeset} ->
        {:noreply, assign(socket, :form, to_form(changeset))}
    end
  end
end

对应的HTML模板文件

<div class="em-gradient flex items-center justify-center">
  <h1 class="font-brand font-bold text-3xl text-white">
    Instantly share Elixir code, notes, and snippets.
  </h1>
</div>


<.form for={@form} phx-submit="create">
    <div class="justify-center px-28 w-full space-y-4 mb-10">
        <.input field={@form[:description]} placeholder="Gist description.." autocomplete="off"/>

        <div>
            <div class="flex p-2 items-center bg-emDark rounded-t-md border">
                <div class="w-[300px] mb-2">
                    <.input field={@form[:name]} placeholder="Filename including extension..." autocomplete="off"/>
                </div>
            </div>
            <.input
                field={@form[:markup_text]}
                type="textarea"
                placeholder="Insert code..."
                spellcheck="false"
                autocomplete="off"
            />
        </div>
        <div class="flex justify-end">
            <.button class="create_button">Create gist</.button>
        </div>
    </div>

</.form>

解决方法

问题根源是Phoenix LiveView默认会保留用户的表单输入状态,即使你替换了空白Changeset,它也可能复用旧状态。以下是两种有效解决方式:

方式1:给to_form添加reset: true选项

修改handle_event成功分支的代码,明确告诉LiveView重置表单状态:

{:ok, _gist} ->
  changeset = Gists.change_gist(%Gist{})
  socket =
    socket
    |> put_flash(:info, "Gist created successfully.")
    |> assign(:form, to_form(changeset, reset: true)) # 新增reset: true
  {:noreply, socket}

方式2:客户端触发表单重置(备选)

如果方式1不生效,可以通过推送事件让客户端执行重置:

  1. 修改HEEX模板的表单,添加phx-success监听:
<.form for={@form} phx-submit="create" phx-success="reset-form">
  <!-- 原有表单内容不变 -->
</.form>

<script>
  window.addEventListener('phx:reset-form', () => {
    document.querySelector('form').reset();
  });
</script>
  1. 在LiveView的成功分支推送重置事件:
{:ok, _gist} ->
  changeset = Gists.change_gist(%Gist{})
  socket =
    socket
    |> put_flash(:info, "Gist created successfully.")
    |> assign(:form, to_form(changeset))
    |> push_event("reset-form", %{}) # 推送重置事件
  {:noreply, socket}

内容的提问来源于stack exchange,提问作者Duck Dodgers

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 01:22:25