Raees678

Raees678

I have a sidebar as a function component that takes the current route as well as a list of items to display:

[%{
  title: "some title",
  route: ~p"/some/route"
}, ...]

The sidebar displays all of the items vertically, and if any of their routes matches the current route, then it adds a little highlight to display the currently selected page.

But now I would like to embed this into my layout, so that all dead and LiveViews can use this. So I put this in my app layout, since I would like the highlighted item to update if i live_redirect. But here is where I run into my issue.
If my app is rendering a dead view, I can access the @conn variable here, and obtain the current route to pass to my sidebar component. But if it is rendering a LiveView @conn is not available, and I must use @socket, where the current route is not available. Is there a way I can obtain the current route from the socket, or is there any other solution for obtaining the current route form the layout regardless if the page being rendered is a dead view/LiveView, and also one that updates across live_redirects etc.

Showing Posts 1 to 8

gpopides

gpopides

You can make use of handle_params

Second parameter as you can see in the documentation is the current uri, so removing the base uri you can get the current path.

Something that you could use is

  @base_path "http://localhost:4000"



  def handle_params(_, @base_path <> path, socket) do
    IO.inspect(path)
    {:noreply, socket}
  end
brady131313

brady131313

I made a hook that I attach in a live session so the current path is always available

def on_mount(:current_path, _params, _session, socket) do
    socket =
      attach_hook(socket, :current_path, :handle_params, fn _params, uri, socket ->
        %{path: path} = URI.parse(uri)
        {:cont, Phoenix.Component.assign(socket, current_path: path)}
      end)

    {:cont, Phoenix.Component.assign(socket, current_path: "")}
  end
Raees678

Raees678 OP

I thought this too, but this does not work in the app.html.heex file. I need the sidebar in this is the file since it is the layout that embeds the <.sidebar current_url={...} items={...}/> component, in all views (both dead views and liveviews).

I think the file is just a template, that I’m assuming compiles down to a function body in the layouts.ex file, similar to how other .heex files get converted into function bodies in the respective controller etc. Since the layout.ex file isn’t a LiveView, putting handle_params in that file doesn’t work. Even attaching a hook doesn’t work since the socket.assigns themselves are unavailable at the time that app.html.heex is evaluated. If I try to print them, even with a hook attached, the value of the assigns is Phoenix.LiveView.Socket.AssignsNotInSocket<>.

gpopides

gpopides

Can you make the sidebar a live view? then you can use handle_params

and in app.html.heex call it with <%= live_render(@conn, Sidebar) %>

Raees678

Raees678 OP

I tried this as well, but this does not work for another reason. If you use live_render then handle_params isn’t invoked, and the app doesn’t even compile, and throws an error. handle_params is only ever invoked for live routes in the router.

Raees678

Raees678 OP

Actually @brady131313 @gpopides, I think I have got it working with a hook. I think I was checking the wrong assigns.socket property and hence I was seeing Phoenix.LiveView.Socket.AssignsNotInSocket<>. When I just check the assigns in the app.html.heex, I can see the hook’s url output in there.

I’m still confused about the order of how the assigns works though, since handle_params is invoked after the mount of a liveview. So at what point do things get put in the assigns of the layout?

sodapopcan

sodapopcan

You can assign @current_path in both a plug and a LiveView hook (not to be confused with a js hook).

Plug:

defmodule MyAppWeb.Plugs do
  import Plug.Conn
  import Phoenix.Controller

  def assign_current_path(conn, _) do
    assign(conn, :current_path, current_path(conn))
  end
end

…and add to your browser pipeline in the router:

MyAppWeb.Router do
  # ...
  import MyAppWeb.Plugs

  pipeline :browser do
    # ...
    plug :assign_current_path
  end
end

Live Hook:

defmodule MyAppWeb.LiveHooks do
  import Phoenix.Component, only: [assign: 3]
  import Phoenix.LiveView, only: [attach_hook: 4]

  def on_mount(:global, _params, _session, socket) do
    socket =
      attach_hook(socket, :assign_current_path, :handle_params, &assign_current_path/3)

    {:cont, socket}
  end

  defp assign_current_path(_params, uri, socket) do
    uri = URI.parse(uri)

    {:cont, assign(socket, :current_path, uri.path)}
  end
end

…and attach the hook in your router:

live_session :some_name, on_mount: [{MyAppWeb.LiveHooks, :global}] do
  # ...
end

(:global can be something more descriptive if you like)

Now @current_path is always available in the layout whether rendered by a live or dead view.

You can use these methods to stuff other data into assigns as well.

EDIT: I forgot the router portion for the plug… see above.

2ND EDIT: Sorry, @brady131313, I blew past your message that offered the same hook advice.

bo_dev

bo_dev

Don’t be sorry, Soda. I am a complete beginner, and your example has been incredibly helpful.

— All posts loaded —

Where Next? Top

Trending in Questions Top

RSP87
I’m working on a project that simulates the bumbl example in the programming phoenix book. It acts almost like an email client. We have a...
New
nseaSeb
Hello, I know there is an approach for handling lists that allows for optimized traversal, but I can’t recall the specific method (somet...
New
brecabral
Documentation While reading the Scoped Routes section, I noticed that the documentation currently refers to a problem without explainin...
New
kpanic
Hi everyone, I am toying with the idea of building a “match maker” for giving personal help to people that wants to start coding. I sta...
New
velrest
So my question is quite simple and i have found no conclusive answer on forum, google or AI. Should we use :erlang.float for Integer to ...
New
asweet-confluent
I recently noticed that Elixir’s Logger defaults its primary log level to :debug when no :logger, :level application configuration is pre...
New
apz
I’m new to elixir and just tried to install the elixirLS extension for VScode(ium) and it is throwing some errors that I would like help ...
New

Other Trending Topics Top

GenericJam
Edit: 2026 May 15 - This post is archived. Mob is alive!! Main docs: mob v0.7.11 — Documentation A bit of explanation for the slightly c...
New
JesseHerrick
Hey, I’m Jesse and I’m the main contributor behind Dexter, a full-featured, lightning-fast Elixir LSP optimized for large codebases. It s...
New
mudasobwa
I am happy to introduce the very α version of the new programming language compiled to BEAM. Welcome Cure. It has literally three kille...
New
garrison
Hobbes is a low-level distributed database for the Elixir programming language. Hobbes provides a simple, safe, and scalable storage lay...
New
marciok
Hi there! We created Gust: A task orchestrator inspired by Airflow. For those who have never heard about Aiflow, it’s a Python-based wor...
New
mhanberg
Hi everyone! The first release candidate for the Expert language server project is now available! We’ve published a press release detai...
New

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews