6

In a normal route:

get /index, MyController, :index

I can simply get the route from Plug.Conn's path_info function.

However if I have a live route, how do I retrieve the current path?

live /index, IndexLive

Bargain23
  • 1,863
  • 3
  • 29
  • 50

2 Answers2

4

You can get the current uri using handle_params callback which is called after mount and before render.

Baruh
  • 92
  • 4
  • 1
    Can you give an example of how to actually use that callback in a template? I want to set an active class depending on the path. – Joe Eifert Jul 25 '20 at 12:50
  • 3
    In `*Web.*Live` module, define `def handle_params(_unsigned_params, uri, socket), do: {:noreply, assign(socket, uri: URI.parse(uri))}`, then you can use `@uri.path`. – en30 Aug 02 '20 at 14:05
3

For those who are finding their way here a few years later, things have come a long way. If you find yourself needing the current path in all views (perhaps for a global navigation element) you'll lose your mind trying to put this on all views.

Making a module like this:

defmodule MyAppWeb.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))}
end

And then dropping it into your live_session:

  live_session :some_session_name, on_mount: [{MyAppWeb.SaveRequestUri, :save_request_uri}] do
    scope "/", MyAppWeb do
      # Your routes
    end
  end

Will result in all live_views having a @request_uri available in the assigns.

Note: the reason phoenix doesn't automatically expose this for you is because the request path can be quite large for some apps; having this in all sockets, all the time, can be expensive. Like everything, a game of trade-offs.. hope this helps!

gcoladarci
  • 889
  • 9
  • 13