Changing form contents on `phx-change`

I am trying to make a “guess the number” game. I thought I’ll use a form with phx_change and text_input. I want to clear the input when the guess is correct. I ended up with this piece of code:

defmodule LiveViewDemoWeb.TestLive do
  use Phoenix.LiveView
  import Phoenix.HTML.Form

  defmodule PlayerInput do
    defstruct [:guessed_number]
  end

  def render(assigns) do
    ~L"""
    <%= f = form_for @changeset, "#", [phx_change: "guess"] %>
    <%= text_input f, :guessed_number %>
    </form>
    """
  end

  def mount(_session, socket) do
    socket =
      socket
      |> assign(%{changeset: player_input_changeset(%{guessed_number: 9})})

    {:ok, socket}
  end

  def handle_event("guess", %{"player_input" => %{"guessed_number" => ""}}, socket) do
    {:noreply, socket}
  end

  def handle_event("guess", %{"player_input" => player_input}, socket) do
    changeset =
      player_input
      |> player_input_changeset()

    case changeset.changes.guessed_number do
      10 ->
        {:noreply,
         assign(
           socket,
           %{changeset: player_input_changeset(%{})}
         )}

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

  defp player_input_changeset(params) do
    types = %{guessed_number: :integer}

    {%PlayerInput{}, types}
    |> Ecto.Changeset.cast(params, Map.keys(types))
  end
end

I can set the initial value in the form by assigning the changeset in mount function. But if I try to do the same in handle_event("guess", ..., it doesn’t reset the field. Even if I put some value there, it is ignored. Am I doing something wrong or is it a known limitation that I can’t change form values inside phx-change event?

It is a known limitation. I’ve found it in the docs of phx-change on the js part.

4 Likes

I’m occurred same problem when build a multiple cooperate excel editor.I need change input value which modified by other client. How do you achieve?

Hey can you share a code snippet with us.

I used hooks mechanism in the end https://hexdocs.pm/phoenix_live_view/Phoenix.LiveView.html#module-js-interop-and-client-controlled-dom
The example from docs does exactly what I wanted.

2 Likes