layout updating when using push_navigate

The application I’m developing has a background gradient that I noticed flashing between liveviews so I inspected the dom and was surprised to see the layout re-rendered w/ each transition to a new liveview. I’m specifying the :layout and I’ve got a live_session wrapping the liveviews in the router and I’m using push_navigate to navigate between liveview. In the documentation it says live sessions keep the same layout, which it is, but I thought that would mean the layout elements was tracked and not re-rendered without changes to their props. Or am I doing something wrong?

Liveview:

  @impl true
  def handle_event("continue", _, socket) do
    {:noreply, push_navigate(socket, to: ~p"/provider/enter-mrn")}
  end

Router:

  scope "/provider", ProviderWeb do
    pipe_through([:browser])

    live_session :provider,
      layout: {ProviderWeb.Layouts, :provider},
      on_mount: [{ProviderWeb.ProviderHooks, :version}] do
      live("/welcome", WelcomeLive, :index)
      live("/enter-mrn", MRNLive, :index)
      live("/enter-dob", DOBLive, :index)
      live("/orders", OrdersLive, :index)
    end
  end

layout:

<link phx-track-static rel="stylesheet" href={~p"/assets/provider"} />

<ProviderWeb.CoreComponents.header />

<main class="provider">
  <%= @inner_content %>
</main>

<footer class="provider">
  <p>
    version: <%= @version %>
  </p>
</footer>

Hello and welcome!

Is says the root layout (:root_layout vs :layout) is not updated between redirects (if they share one), everything else is. This is the static layout generally shared between live views and dead views alike and is not change tracked—it’s generally rendered once can have its title updated through the special assign :live_title.

1 Like

I was hoping I did something wrong :frowning_face:

I appreciate your reply.

Have you tried creating a separate root layout specific to that live session? You should be able to do something like this:

live_session :provider,
      root_layout: {ProviderWeb.Layouts, :provider_root},

If you wanted to keep a single root layout, you could move the shared unchanging parts of the :layout into the :root_layout and put it behind a check based on the live_session by checking an assign set on mount or on_mount for the name of the live_session, which should be available somewhere in the session callback parameter.

1 Like

thanks for the suggestion! the css attached to the layout was causing the issue so I created a plug that holds a list of css & js files that I loop through in the root layout. I’ll take your suggestion though and move the other common parts in the root layout behind a check.

1 Like