The key change is wrapping the entire sidebar in a turbo frame that can be reloaded on each interaction.
Just so I understand it, I want to break down how it works.
On the initial page load, a partial,
playlists/playlists loads that contains the entire sidebar wrapped in a turbo frame
This ensures that any interaction within this frame will re-render the frame if the response contains a
playlists turbo frame.
The first interaction is clicking on the "Add" Playlist button to load the new playlist form. Clicking on the button triggers a request to
playlists#new which re-renders the
playlists/playlists partial with just one change, a really clever use of blocks to include the new playlist form.
<%= render "playlists/playlists" do %> <div class="px-3"><%= render "form" %></div> <% end %>
By including a block to the
render call, any content passed to the block will be rendered in the position of the a
yield statement within that partial. This allows the form to be rendered on top of the list of playlists.
<%= turbo_frame_tag "playlists" do %> <div class="space-y-4"> <div> <div class="flex justify-between items-center pl-6 pr-3"> <h2 class="relative text-lg font-semibold tracking-tight">Playlists</h2> <%= render_button as: :link, href: new_playlist_path, variant: :ghost, class: "px-2" do %> + Add <% end %> </div> <%= yield %> <div dir="ltr" class="relative px-1"> <div class="h-full w-full rounded-[inherit]"> <div style="min-width: 100%; display: table"> <div data-controller="playlists"> <%= render collection: Playlist.all, partial: "playlists/playlist" %> </div> </div> </div> </div> </div> </div> <% end %>
Since the initial call to
playlists/playlists when we first loaded the page included no block, this partial rendered the frame without the new playlists form. But when we click that button and re-render
playlists/playlists in the context of
playlists#new, because we're passing a call to render the block when we render the
playlists/playlists partial, the form will appear.
In the same way, when the new form is submitted within the
playlists turbo frame, if the response contains a
playlists turbo frame, the frame will be re-rendered without a page reload.
Sure enough, if we look at
playlists#create, it redirects to
playlists/index, which just re-renders
playlists/playlists and the
playlists turbo frame. When a the new playlist form is submitted, re-rendering the
playlists/playlists partial will now contain the playlist that was just created.