I am working on an app composed of mostly discrete components that I am trying to implement with Live View. For now I have built this as a parent live view and template that renders several child live views/templates. I like this because it separates template and event handler code into files that are logically related.
For example, one component is a list of items with an input field that can be used to filter the list. Another component is a form with checkboxes that can be used to update user preferences. When the controller renders the page for the first time, the assigns for all of these components are passed to the parent view via the session and the session is used to mount each child view - like this simplified example:
page_controller.ex
def index(conn, _params) do
...
LiveView.Controller.live_render(conn, PageLive, session: %{prefs: prefs, items: items})
end
page_live.ex
def render(assigns), do: PageView.render("index.html", assigns)
def mount(session, socket) do
{:ok, assign(socket, items: session.items, preferences, session.preferences}
end
index.html.leex
<%= live_render(@socket, PreferencesLive, session: @session) %>
<%= live_render(@socket, ItemsLive, session: @session) %>
items_live.ex
def render(assigns), do: PageView.render("items.html", assigns)
def mount(_session, socket), do: {:ok, assign(socket, session.items)}
def handle_event("update_items", value, socket) do
...
{:noreply, assign(socket, :items, updated_items)}
end
preferences_live.ex
mirrors items_live.ex
- it handles an “update_preferences” event and renders preferences.html
.
preferences.html.leex
and items.html.leex
are simple templates that only refer to @preferences
and @items
assigns, respectively.
So, when the user triggers an event in a given component, that child live view event handler is called and the child template is re-rendered.
My problem arises because the components are not completely discrete. In the context of the example above, it turns out that when the user’s preferences change, the data underlying the items list may change, but I don’t see a way to trigger a refresh of the items list view from the event handler in preferences_live.ex
.
I assume I could make this all work by abandoning the idea of having separate templates for different parts of the page. I get that if it was all just one view that only the parts of the page with updated assigns get re-rendered; I just like organizing the code in smaller logical pieces. I’m hoping that there is some alternative structure for this situation that I should have used, or that I have just missed some obvious feature of Live View that would allow me to update the assigns for one child template in the context of the event handler for a different child template.