Do you have to use hidden form fields in a multi-step form?

Greetings,

Previous title of this post: Phoenix.new generated params not extracted on submit of 2nd step in multi step form on liveview

I am revising this post completely because I used phx.gen.live to generate a simple test case and it confirmed the previous behavior but now I have two apparent fixes.

My question: Are either of the following two fixes appropriate or is something else wrong?

The problem is that this fails on second submit because params is an empty map:

def render(assigns) do
    ~H"""
    <Layouts.app flash={@flash} current_scope={@current_scope}>
      <.header>
        {@page_title}
        <:subtitle>Use this form to manage junk records in your database.</:subtitle>
      </.header>
    <%= if @step == :details do %>
      <.form for={@form} id="junk-form" phx-change="validate" phx-submit="save">
        <.input field={@form[:name]} type="text" label="Name" />

        <.input field={@form[:address]} type="text" label="Address" />

        <footer>
          <.button phx-disable-with="Saving..." variant="primary">Save Junk</.button>
          <.button navigate={return_path(@current_scope, @return_to, @junk)}>Cancel</.button>
        </footer>
      </.form>
    <% else %>
        <.form for={@form} id="junk-form" phx-change="validate" phx-submit="save">
        <footer>
          <.button phx-disable-with="Saving..." variant="primary">Save Junk</.button>
          <.button navigate={return_path(@current_scope, @return_to, @junk)}>Cancel</.button>
        </footer>
      </.form>
    <% end %>
    </Layouts.app>
    """
  end

There are two ways I can make it pass.

One way is to patch the event handler:

# def handle_event("save", %{"junk" => junk_params} = params, socket) do
  def handle_event("save", params, socket) do
    # A PATCH:
    junk_params =
      if Map.has_key?(params, "junk") do
        params["junk"]
      else
        socket.assigns.form.params
      end

       junk = %Junk{user_id: socket.assigns.current_scope.user.id}
       changeset =
          Junkcontxt.change_junk(socket.assigns.current_scope, junk, junk_params)
          |> Map.put(:action, :validate)

    case socket.assigns.step do
      :details ->
          {:noreply,
           socket
           |> assign(:step, :payment)
           |> assign(:form, to_form(changeset))
           |> put_flash(:info, "Organization details look good! Now let's set up payment.")}

      :payment ->
         save_junk(socket, socket.assigns.live_action, junk_params)
      end

  end

Or, another way is to include hidden inputs in the form:

 <% else %>
        <.form for={@form} id="junk-form" phx-change="validate" phx-submit="save">
        <.input field={@form[:name]} type="hidden" />

        <.input field={@form[:address]} type="hidden" />

        <footer>
          <.button phx-disable-with="Saving..." variant="primary">Save Junk</.button>
          <.button navigate={return_path(@current_scope, @return_to, @junk)}>Cancel</.button>
        </footer>
      </.form>
    <% end %>

Thanks in advance.