I’ve been reading the book “Programming Phoenix LiveView” for a while now. Basically on our index page we’ve got products listed and then when we click on the edit button a modal is rendered with a form with the product details which you can edit.
Here’s a screenshot:
After taking a look at the code, I can see the snippet below in index.html.leex
which does the rendering of the modal:
<%= if @live_action in [:new, :edit] do %>
<%= live_modal @socket, PentoWeb.ProductLive.FormComponent,
id: @product.id || :new,
title: @page_title,
action: @live_action,
product: @product,
return_to: Routes.product_index_path(@socket, :index) %>
<% end %>
And if I navigate into where live_modal/3
is defined, I can see:
def live_modal(socket, component, opts) do
path = Keyword.fetch!(opts, :return_to)
modal_opts = [id: :modal, return_to: path, component: component, opts: opts]
live_component(socket, PentoWeb.ModalComponent, modal_opts)
end
Which then calls live_component/3
. However if we look into PentoWeb.ModalComponent
we see that in the render
function live_component/3
is called as well.
# pento_web/live/modal_component.ex
defmodule PentoWeb.ModalComponent do
use PentoWeb, :live_component
@impl true
def render(assigns) do
~L"""
<div id="<%= @id %>" class="phx-modal"
phx-capture-click="close"
phx-window-keydown="close"
phx-key="escape"
phx-target="#<%= @id %>"
phx-page-loading>
<div class="phx-modal-content">
<%= live_patch raw("×"), to: @return_to, class: "phx-modal-close" %>
<%= live_component @socket, @component, @opts %>
</div>
</div>
"""
end
@impl true
def handle_event("close", _, socket) do
{:noreply, push_patch(socket, to: socket.assigns.return_to)}
end
end
And there’s this diagram from the book:
So could you please tell me what’s role of live_component
here and why it’s called twice? This might be an unimportant question but I am just wondering the details.