Need help with simple webmail layout

Hello,

I’m trying to make a simple three column layout:

  • navigation
  • list of messages
  • content of a message

I created two routes to test this layout

live_session :default do
	live "/messages", MessagesListLive
	live "/messages/:message", MessagesShowLive
end

Live views

defmodule Webmail.MessagesListLive do
  use Phoenix.LiveView, layout: {Webmail.LayoutView, "live.html"}

  def render(assigns) do
    ~H"""
    	<div class="app">
    		<div class="menu">...</div>
			<%= live_render(@socket, Webmail.Messages.ListLive, id: "messages", session: %{}, sticky: true, container: {:div, class: "list"}) %>
    	</div>
    """
  end
end

defmodule Webmail.MessagesShowLive do
  use Phoenix.LiveView, layout: {Webmail.LayoutView, "live.html"}

  def render(assigns) do
    ~H"""
    	<div class="app">
    		<div class="menu">...</div>
			<%= live_render(@socket, Webmail.Messages.ListLive, id: "messages", session: %{}, sticky: true, container: {:div, class: "list"}) %>
			<div class="content">...</div>
    	</div>
    """
  end
end

defmodule Webmail.Messages.ListLive do
  use Phoenix.LiveView, layout: {Webmail.LayoutView, "live.html"}

  def render(assigns) do
    ~H"""
    	<ul>
    		<li><a data-phx-link="redirect" data-phx-link-state="push" href="/messages/message0">message 1</a></li>
    		<li><a data-phx-link="redirect" data-phx-link-state="push" href="/messages/message1">message 1</a></li>
    		<li><a data-phx-link="redirect" data-phx-link-state="push" href="/messages/message2">message 2</a></li>
    		....
    		<li><a data-phx-link="redirect" data-phx-link-state="push" href="/messages/message100">message 100</a></li>
    	</ul>
    """
  end
end

When you scroll the list and click on any link, live view will load that message but you will lost scroll position of that list. I have no idea how to make it work, I tried sticky option for liveview, changing Webmail.Messages.ListLive to be a live component without success. I found that moving live_render of Webmail.Messages.ListLive to template root.html.heex fixes scroll position issue but this is not really a solution.

I would like to know if there is a better way to make that layout.

Keep in mind that, I’m playing with elixir/phoenix for just a few days :wink:

I figured it out, I changed MessagesListLive and MessagesShowLive to the same live view MessagesLive and data-phx-link=“redirect” to data-phx-link=“patch” in ListView and my scroll issue is gone.

Is there is a way to make it work with two different live views ?

Welcome to the forum :rocket:

You can push an event targetting the id of the other live view, or a component within it, which will then invoke the relevant handle_event on its process.

My question was more about spliting buissnes logic of listing/filtering list of mails and showing a single mail to two different live views while still maintaining a scroll position of that list. Only solution I found so far is a single live view resposible for listing and showing mails. I don’t really like puting to mutch code in one live view, but if there isn’t a better way for doing it then I will live with that :wink:

Too much code in one module, or too much code in one process? If you want to split logic between different processes, it is going to be tough and brittle at best.

To much code in one file :wink:

That can be done. You can just defdelegate to other module.

That is a good idea, I’ll do that, thank you :slight_smile: