That’s interesting, thanks @benwilson512! will check that out.
I had just prepared an update, will post it anyway.
By the way, I am also integrating (matching) the layout and navigation of my LiveView with my regular views.
Same final structure, navigation contains both live patches and regular links:
<!-- app.html.eex -->
<div>
<div>
<p class="alert alert-info" role="alert"><%= get_flash(@conn, :info) %></p>
<p class="alert alert-danger" role="alert"><%= get_flash(@conn, :error) %></p>
<div>
<header>
<%= render "static_nav.html", nav: get_nav(@conn) %>
</header>
<%= @inner_content %>
</div>
</div>
</div>
<!-- live.html.leex -->
<div>
<p class="alert alert-info" role="alert" phx-click="lv:clear-flash" phx-value-key="info"><%= live_flash(@flash, :info) %></p>
<p class="alert alert-danger" role="alert" phx-click="lv:clear-flash" phx-value-key="error"><%= live_flash(@flash, :error) %></p>
<%= @inner_content %>
</div>
Anyway, the following seems to be working:
# liveview module
def mount(%{} = request_params, %{} = session, socket) do
...
assigns = [
...
component_message: %{},
component_module: MyLiveComponent,
component_id: :live_component_id,
...
]
{:ok, assign(socket, assigns)}
...
end
# liveview template
<%= live_component @socket, @component_module, id: @component_id, msg: @component_message %>
# grandchild component
send self(), {:pass_down, %{setting: :updated_setting}}
# liveview module
def handle_info({:pass_down, %{} = payload}, socket) do
{:noreply, assign(socket, component_message: payload)}
end
# child component
def update(%{msg: msg} = _assigns, socket) do
# read msg, do stuff
send self(), {:pass_down, %{}}
{:ok, socket}
end