Raees678
How can I obtain the current url to pass to a functional component from the app.html.heex layout when rendering liveviews?
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.
Most Liked
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.
Raees678
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<>.
Raees678
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.
Last Post!
bo_dev
Don’t be sorry, Soda. I am a complete beginner, and your example has been incredibly helpful.
Popular in Questions
Other popular topics
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #channels
- #elixirconf
- #exunit
- #discussion
- #code-sync
- #javascript
- #podcasts
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixir-ls
- #phoenix_html
- #iex
- #blog-post
- #graphql
- #genstage
- #ai
- #websockets
- #supervisor
- #elixirconf-us
- #advent-of-code
- #distillery
- #processes
- #forms
- #api
- #metaprogramming
- #security
- #hex









