Hey everyone!
I’m currently working on a new Phoenix LiveView app with the following setup:
Phoenix: 1.7.14
LiveView: 1.0 rc6
Layout Overview
My layout structure looks like this:
root.html.heex renders the live.html.heex content.
live.html.heex initially renders HomeLive for the ‘/’ route.
Layout Components:
site_header (function component)
sidebar (function component)
footer (function component)
landing_page (rendered inside HomeLive)
The site_header and sidebar components are rendered outside of HomeLive, whereas the main content area, including the landing_page, is rendered inside HomeLive.
Here’s a sample snippet from live.html.heex:
<main class="...">
<.sidebar_container />
<div class="...">
<.site_header />
<div class="...">
<div class="...">
<.flash_group flash={@flash} />
<%= @inner_content %>
</div>
</div>
<.footer />
</div>
</main>
Problem Statement
I’m trying to set up the initial state using a module similar to nav.ex in the live_beats app ( fly-apps/live_beats (github.com)):
def on_mount(:default, _params, _session, socket) do
# sets assigns, streams, etc.
end
In live_beats, nav.ex is called/applied in the router:
scope "/", LiveBeatsWeb do
pipe_through :browser
live_session :default, on_mount: [{LiveBeatsWeb.UserAuth, :current_user}, LiveBeatsWeb.Nav] do
live "/signin", SignInLive, :index
end
live_session :authenticated,
on_mount: [{LiveBeatsWeb.UserAuth, :ensure_authenticated}, LiveBeatsWeb.Nav] do
live "/:profile_username/songs/new", ProfileLive, :new
live "/:profile_username", ProfileLive, :show
live "/profile/settings", SettingsLive, :edit
end
end
This setup makes the state in nav.ex available, so the sidebar can access @active_tab and other shared assigns.
Issue
I tried a similar setup in my app:
scope "/", MyAppWeb do
pipe_through :browser
live_session :default,
on_mount: [MyAppWeb.Nav] do
live "/", HomeLive
end
end
However, in my layout, only HomeLive has access to the state defined in nav.ex. The function components like sidebar and header (which are rendered outside of HomeLive) don’t have direct access to it. For instance, I can’t access @sidebar_open in the sidebar component.
Question
How can I make the initial state defined in lib/my_app_web/live/nav.ex accessible to my layout components like the sidebar and header? I’d like them to have access to shared state without duplicating logic.
I’ve done some research but couldn’t find a reliable solution, hence reaching out here. Any guidance or patterns to achieve this would be greatly appreciated!
Thanks in advance!