How to redirect to another page, after saving a record by using phx-change and phx-debounce without phx-submit?

I have a condition to save a new record of a ‘name’ field, to be automatically saved after user click away from the text_input (unfocus/blur), without the save button.

I have successfully used phx-change along with phx-debounce to save the unique name and minimum length of 3 characters. However, after saving, it does not redirect to the show page.How to achieve the redirection without phx-submit like this?

Thank you.

issuing a push_redirect(socket, to: ...) from the phx-change event should be enough. Do you have a redirect in place? If so, are you seeing any server or js console errors? Can you provide your LV source?

1 Like

Wow, thank you for the response @chrismccord.

This is my LiveView file

defmodule PortalWeb.SignLiveNew.Form do
  use Phoenix.LiveView
  require IEx

  alias Portal.Fleet
  alias Portal.Fleet.Sign
  alias PortalWeb.LiveSignView
  alias PortalWeb.Router.Helpers, as: Routes

  def render(assigns), do: LiveSignView.render("form.html", assigns)

  def mount(session, socket) do
    {:ok,
     assign(socket,
       changeset: Fleet.change_sign(%Sign{}),
     )}
  end

  def handle_event("verify_submit", %{"sign" => params}, socket) do
    IO.inspect(params)
    changeset = Fleet.change_sign(%Sign{})

    case Fleet.create_sign(params) do
      {:ok, _sign} ->
        {:stop,
         socket
         |> put_flash(:info, "Sign created successfully.")
         |> redirect(to: Routes.sign_path(socket, :index))
         }

      {:error, %Ecto.Changeset{} = changeset} ->
        {:noreply, assign(socket, changeset: changeset)}
    end

    {:noreply, assign(socket, params: params)}
  end

end

This is the template.

<%= f = form_for @changeset, "#", [phx_change: :verify_submit] %>

  <%= text_input f, :name, placeholder: "Name", "phx-debounce": "blur" %>
  <%= error_tag f, :name %>
</form>

So far there is no error shown on the iex or js console, even if the input is not correct. However, it is not saving when the input is incorrect.

Your handle_event returns the socket unchanged. Remember that elixir is immutable, so your case statement executes, but the socket is not changed because you return the old one afterwards. Update your handle_event to:

  def handle_event("verify_submit", %{"sign" => params}, socket) do
    IO.inspect(params)
    changeset = Fleet.change_sign(%Sign{})

    case Fleet.create_sign(params) do
      {:ok, _sign} ->
        {:noreply,
         socket
         |> put_flash(:info, "Sign created successfully.")
         |> redirect(to: Routes.sign_path(socket, :index))}

      {:error, %Ecto.Changeset{} = changeset} ->
        {:noreply, assign(socket, changeset: changeset, params: params)}
    end
  end
8 Likes

This is working perfectly. Thank you @chrismccord