Conn.request_path doesn't change in header

 λ  elixir -v
Erlang/OTP 23 [erts-11.1.7] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] [hipe] [dtrace]

Elixir 1.12.3 (compiled with Erlang/OTP 22)
 λ  mix phx -v
Phoenix v1.6.4

root.html.heex

  <body>
    <%= render PragmaticWeb.SharedView, "header.html", assigns %>
    <%= @inner_content %>
    <%= render PragmaticWeb.SharedView, "footer.html", assigns %>
  </body>

header.html.heex

<%= @conn.request_path %>
<%= Phoenix.Controller.current_path(@conn) %>

<div class="hidden md:block md:ml-10 md:pr-4 md:space-x-8 w-full menu">
    <%= live_redirect "Home", to: "/", class: if @conn.request_path == "/", do: "active", else: "" %>
    <%= live_redirect "Discover", to: "/discover", class: if @conn.request_path == "/discover", do: "active", else: "" %>
    <%= live_redirect "About", to: "/about", class: if @conn.request_path == "/about", do: "active", else: "" %>
    <%= live_redirect "Contact Us", to: "/contact", class: if @conn.request_path == "/contact", do: "active", else: "" %>
    <%= live_redirect "Login", to: "/login", class: "float-right" %>
</div>

Hi, i want to highlight the menu item in navigation bar, but <%= @conn.request_path %> in the header partial doesn’t change at all between clicks, there are solutions in the forum. but i want to know why conn.request_path does’nt change at all. the phoenix_active_link also use conn.request_path.

related:

@dfang your header and footer should be part of your live layout, not part of your static layout. Then they will be able to access assigns on the socket.

1 Like

hi @benwilson512, thanks for your help,

currently the header and footer is in root.html.heex, when i move it to live.html.heex , i got this error:

ArgumentError at GET /contact
assign @conn not available in template.
Please make sure all proper assigns have been set. If you are
calling a component, make sure you are passing all required
assigns as arguments.
Available assigns: [:__changed__, :flash, :inner_content, :live_action, :socket]

Right, the conn is not available anymore, you need to use values on the @socket now.

1 Like

thre are many related issues if you search navbar. it seems adding a active class is not so easy in phoenix liveview like in rails.

eg.

  1. Have a live footer and header with LiveView
  2. Liveview Navbar, component in layout receives socket? - #4 by darkmarmot
  3. Both layouts for liveview and normal view renders when using live_render on root.html.leex - #2 by Matsa59
  4. and more

finally, i worked this out.

  1. put render PragmaticWeb.SharedView, "header.html", assigns in live.html.leex not root.html.leex

  2. use @socket.view instead of @conn.request_path to add active css class
    <%= live_redirect "Home", to: "/", class: if Kernel.inspect(@socket.view) == "DemoWeb.HomeLive", do: "active", else: "1" %>

  3. it’s better to use live component

i uploaded a demo to github

Absolutely. If you want your navigation to be live, it needs to be inside a live layout.

On the other two points, I would recommend this tutorial: Active nav with LiveView · Fly

It will show you how to use the lifecycle hooks to add an @active_tab assign that you will use to set the active class. Whether or not it is easier than Rails I do not know, but it is very flexible!

1 Like

@mcrumm thanks for your reply, attach_hook in on_mount is very useful !!!

1 Like