Search code examples
elixirphoenix-live-view

Reset Form After Submission Elixir LiveView


I'm pulling out my hair because I know it's probably something really small I'm missing, But I'm just trying to clear the form after a successful form submission - A Gist is created with no issues.

Here's my simple create_gist_live.ex file:

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

And then here's the corresponding .html.heex file:

<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>

The form works correctly in the sense that the data is persisted to the postgres database upon filling all the fields. And we get validation errors if there are missing fields. But I just can't get the form to clear upon a successful submission. I assumed I was doing the right thing by creating a blank Gist changeset and assigning it to form but that's not working for some reason.


Solution

  • You need to also use phx-change on your form to keep the html input value and the assigned changeset value the same.

    Change your opening form element tag to this:

    <.form for={@form} phx-submit="create" phx-change="change">
    

    and add this to your live view:

    def handle_event("change", params, socket) do
      changeset = Gists.change_gist(%Gist{}, params["gist"])
      socket = assign(socket, :form, to_form(changeset))
      {:noreply, socket}
    end
    

    With these changes, you will be updating the form as your html input changes.

    LiveView will only update the HTML if an assign changes. In your original code, you were never actually changing the assign. It was always a form with a new changeset.