Form resubmission after live_render on create

Hi! I’m learning Elixir and Phoenix and I’ve just started implementing a few live_view features.

Summary: I’m doing a live_render after a form submission. And when I refresh the page, the form gets resubmitted.

Detail: In the router.ex I’m not using any live routes. I figured I would only use routes to controller functions and do live_render there for those templates which would need it.

The Index for things is one of the views I want live, to add a live dates filter and to append new created things on other sessions, all of that which works correctly. ThingLive.Index module has its mount function and all, and the leex template is properly displayed after this live_render call from the controller:

  def index(conn, _params) do
    things = fetch()

    live_render(conn, ThingLive.Index, session: %{
      "user" => conn.assigns.user,
      "things" => things
    })
  end

But from the index you can go and add a new thing, which posts the form (nothing live_view there, just a regular form submission to a controller function create).

Once the render happens, if I reload the page, the form gets submitted again and this function gets executed. Why does this happens and how can I prevent it?

  def create(conn, %{"thing" => thing_params}) do

    case Thing.create_thing(conn.assigns.user, thing_params) do
      {:ok, _thing} ->
        things = fetch()

        conn
        |> put_flash(:info, "Thing created successfully.")
        |> live_render(ThingLive.Index, session: %{
            "user" => conn.assigns.user,
            "things" => things
          })

      {:error, %Ecto.Changeset{} = changeset} ->
        render(conn, "new.html", changeset: changeset)
    end
  end

What happens if you remove all the live_render calls? From reading your description I’m not convinced that liveview is the cause of your issue.

If you’re able to put an example project up on github (or your favourite equivalent) that reproduces the problem we’ll be able to take a look.

This setup is a bit odd, since you’re sort of half using live view, half not. Regardless, on successful create you should redirect to the show page instead of rendering the live view after the create. If you want a liveview at that point you should render the live view from the show page.

Will give it a shot removing the live_render calls. The whole thing is on github. As I’ve said, it’s a learning project (I’ve just started with Elixir and functional programming), but I’m planning to use it once it’s ready.

Controller involved is slots. Here’s with links, for you to be able to take a look: coopagenda/lib/coopagenda_web/controllers/slot_controller.ex

Should I be using only LiveViews? I thought I could do a mix, and use it for those pages on which I expect to have Live behavior. But I’m probably confused about it, I’ve been having some issues understanding it.

It’s true the previous setup was redirecting to the show page. But I would like it to go back to the index and not the show page, once the entity is created.

See, I think the problem is here. You use live_render from the create action, which gets called on a POST request. Essentially, you cannot redirect with a live_render, but it renders where it is. Most likely, that’s why on refresh, the form is re-submitted.

What you can try to do is redirect normally to an index.html.eex file, in which you would have the live_render. But this feels dirty. Second option would be to add a live route in router.ex: live "/slots" (in this case, also ignore the :index in the resources macro)

Got it. That’s probably it. Will implement the fix tomorrow, and correct the way I’m thinking about LiveViews according to the way live_render renders.

Thanks!