So I’ve read a lot and experimented with and used LiveView a lot, but there is one thing I can’t wrap my head around.
I have an application like this:
+--------------------------------------------------------+
| |
| Header |
| |
+----------------+---------------------------------------+
| | |
| | |
| Navigation | Main |
| | |
| | |
| | |
| | |
+----------------+---------------------------------------+
With these requirements:
- multiple liveviews need to use this layout
- the layout is quite complex so I’d rather not duplicate it in every liveview template.
- The Navigation shows the current selected item.
- Header and Main need access to all assigns of the current liveview.
At the moment I took some inspiration from the live dashboard on how to create the navigation.
My current solution looks like this:
I have a parent page
that now renders the layout
# simplified the layout
<div>
<%= live_component @socket, NavLive, links: @links, current_user: @current_user %>
<header>
<%= render_header(@socket, @page, assigns) %>
</header>
</div>
<main>
<%= live_render(@socket, @page, id: @page, session: %{"live_action" => @live_action, "params" => @params, "current_user" => @current_user}) %>
</main>
live_render
will then render the child based on the current route and render_header
will also call a method on my child view.
The problem with this solution is:
-
render_header
is a custom method and doesn’t have access to the assigns created in the mount of the child view - I have to do some ugly things to pass the
live_action
,current_user
around to child views - but this works.
(1.) is thus the main problem. How do you people solve this?
In React
I would probably create a component ApplicationLayout
that takes 3 props: Header
, Navigation
and Main
and every page could use that.
<ApplicationLayout
header={<div>custom html</div>}
navigation={<div>custom html</div>}
main={<div>custom html</div>}
/>
I don’t see how this can be done in liveview, unless I’m missing something?
How do you build these kind of complex layouts?