SideBar with LiveView

I’ve building a website with LiveView, and I’m getting some issues trying to understand what is the best way to include a navbar with a search box. Since the navbar exists in all the pages, I’m adding the html code to the app.html.eex file, but since that isn’t rendered using @socket, not sure what is the best way to do it.

Maybe the new live_components can help ?

1 Like

Have you tried embedding a totally separate liveview in app.html.eex with something like <%= live_render(@conn, DemoWeb.WeatherLive) %>? It should work ok if the search function relates to the whole app rather than the specific page you are viewing.

4 Likes

I have the same problem, and didn’t find a great solution so far. The problem with using a separate liveview is that it can’t use live_link (only the main liveview can), so all search and sidebar links trigger a full page reload. This makes the experience a bit poor compared to Turbolinks because of the delay and loading spinner.

I have no experience in this problem, but thinking loudly:
Can’t we just recursively send a message to parents until we reach the root LiveView?

%{parent_pid: prarent_pid} when is_pid(parent_pid) -> send(parent_pid, ...)
%{parent_pid: nil} -> live_redirect(socket, ...)

@mindok @dom I thought I used live_render before, but this time worked. I can use live_link inside the new LiveView.

In app.html.eex I’have:

<%= live_render(@conn, DemoWeb.SidebarLive, session: %{session_id: Plug.Conn.get_session(@conn, :session_id)}) %>
...
<%= render @view_module, @view_template, assigns %>

Inside the sidebar.html.leex

...
<%= live_link "Painel", to: Routes.live_path(@socket,DemoWeb.DashboardLive.Index) %>
...

My objective was to have a sidebar with a search box and every time someone typed there, it will change the main view to show the results from the search box.

One of the issues that I had was communicating between LiveViews. I end up creating a unique string (called session_id) and send a broadcast saying that the there is search results. The only problem with this approach is that I need to set up the same behaviour for all possible views. Probably this would be better to have only one main LiveView and everything else is LiveComponent ?

EDIT

I’ve changed in app.html.eex from this:

<% render @view_module, @view_template, assigns %>

to this:

<%= live_render(@conn, DemoWeb.LayoutLive, session: %{session_id: Plug.Conn.get_session(@conn, :session_id), view_module: @view_module, view_template: @view_template, live_view_module: assigns.live_view_module, content: assigns.content}) %>

And in the layout.html.leex I have:

<%= if !is_nil(@search_result) do %>
Show search result
<% else %>
  <%= render @view_module, @view_template, assigns %>
<% end %>

The live_link works if I don’t search input is empty or I can type something but don’t click in a live link. If I type something and click in a live_link, it will stop working (the live_links).

Internally, it works perfectly, but the view isn’t updated with the live_link information. It only updates if I type something in the search box.

1 Like

@chrismccord, maybe you can shine some light regarding my comment above ? I will try to create a repository simulate this behaviour.

1 Like