Creating a BreadCrumb component that renders the proper links was a piece of cake but I had the URL/request_path hardcoded during the development of rendering it.
Now I am completely flummoxed as to how to get the the current URL/request_path into my component. I have tried both as a live_component and a Phoenix.Component. While I can get to request_path at various points in the lifecycle there does not seem to be an idiomatic solution for the driving functionality within components based on the URL/request_path. It seems like the best place would be to solve this in a live_session on_mount call.
assign(:request_path, socket.private.connect_info.request_path)
this does work but it is not presented down to my component
Is there a place that the current path exists regardless of activities via “patch”, “push_patch”, 'navigate", and “push_navigate”?
Have you considered hooking into LiveView’s handle_params/3 callback to keep the request_path assign updated?
The handle_params/3 callback is invoked after mount/3 and before the initial render. It is also invoked every time <.link patch={...}> or push_patch/2 are used. It receives the request parameters as first argument, the url as second, and the socket as third.
Hmm, are you passing the assign down to the component? It must be passed explicitly for it to be available.
I would expect socket.private.connect_info.request_path to be that place. You’d probably want to set it as an assign in mount callback and then keep it updated in handle_params callback.
Confirm, handle_params is what you want. The second argument its he request URI. You can even set up a lifecycle hook to always place a @request_path assign into every LiveView to pass down to your components
I did think about that but doesn’t mean that the breach_crumb would have to be a liveview rather than a component? If that is the case how do you inject a new liveview into app.html.heex?
This is how I handled this for a side Nav component that needed to track the “active” link:
defmodule MyAppWeb.Path do
@doc """
Sets the path from the connection as :current_path on the socket
"""
def on_mount(:put_path_in_socket, _params, _session, socket),
do:
{:cont,
Phoenix.LiveView.attach_hook(
socket,
:put_path_in_socket,
:handle_params,
&put_path_in_socket/3
)}
defp put_path_in_socket(_params, url, socket),
do: {:cont, Phoenix.Component.assign(socket, :current_path, URI.parse(url).path)}
end
Then in your router in the live session you add it:
live_session :require_authenticated_user,
on_mount: [
{MyAppWeb.UserAuth, :ensure_authenticated},
{MyAppWeb.Path, :put_path_in_socket}
] do
Then you can access it in your app.html.heex layout as @current_path: