LiveView - showing the active path

I have layout with a navigation bar and a content view. In my root layout I do the rendering as follows:

<div>
  <%= render("sidebar.html", assigns) %>
  <%= @inner_content %>
</div>

Inside sidebar.html:
<div>
  <%= live_redirect to: Routes.live_path(@conn, MyApp.RouteLive), class: is_active(@conn.path_info) %>
</div>

However when using live_redirect, the sidebar template is not re-rendered when a new LiveView is routed to. I’m wondering how to solve it.

I’ve tried to use live_render inside the root layout to render a SideBar LiveView. Doesn’t work as handle_params can’t be called since this isn’t the “main” liveview.

Any pointers how to separate my side bar that uses live_redirect for the links without tying it up with all my other content LiveViews?

It works if I use a normal redirect (as the page is rerendered), but this will tear down the LiveView socket.

2 Likes

Take a look at how LiveDashboard achieves this: live.html.leex, live_helpers.ex, menu_live.ex

You can assign a menu variable inside your liveviews that you can also pass to the logic holding your menu (be it a live_view, live_component or even a simple template). But you will need to move it from your root layout inside your live layout.

8 Likes

Thank you, that is quite concise.

Here’s how I did it:

Create a new module to assign “current_uri” to your socket. I only set the path string to the assigns, since I don’t want/need the whole URI enchilada.

defmodule GamedropWeb.SaveRequestUri do
  def on_mount(:save_request_uri, _params, _session, socket),
    do:
      {:cont,
       Phoenix.LiveView.attach_hook(
         socket,
         :save_request_path,
         :handle_params,
         &save_request_path/3
       )}

  defp save_request_path(_params, url, socket),
    do: {:cont, Phoenix.Component.assign(socket, :current_uri, URI.parse(url) |> Map.get(:path))}
end

Call this module from your router.ex:

live_session :current_user,
  on_mount: [
    {GamedropWeb.UserAuth, :mount_current_user},
    {GamedropWeb.SaveRequestUri, :save_request_uri}
  ] do
  live("/users/co.... *snip*
end

And then you can just call this from your liveview templates or layouts.

<p>@current_uri} /></p>