How do I use turbo frames to create tab navigation?

I’m trying to wrap my head around using Hotwire with Rails.

I have simple tab navigation menu that is at the top of my page inside a <%= turbo_frame_tag 'account_navigation', target: 'tab_content' do %> with a Dashboard link, Calendar link, etc.

Underneath that I have a <%= turbo_frame_tag 'tab_content', src: dashboard_path %> that loads the dashboard.html.erb content initially.

What I would like is for when I click a tab, it replaces the tab_content turbo frame with the corresponding content, e.g. Clicking the calendar link should replace the tab_content with the turbo frame in calendar.html.erb.

Is there a way to do this without including the tab navigation code on every page that I want to use as tab_content ?

What if you create additional templates to wrap these existing ones, like: tab_calendar.html.erb, this file would contain the tab navigation related code, as well as render the original template, it would let the original calendar.html.erb untouched

So after a lot of video watching/pausing, I figured out a solution and its actually surprisingly easy.
If you are wanting to create a tab navigation like I did where the navigation menu is outside of the turbo frame so you aren’t repeating code over an over, you just need to add a data-turbo-frame="MyTurboFrame" attribute to your nav links. Here is an example using Rails.

# show.html.erb
# Nav menu/ not wrapped in a turbo_frame
<ul class="tabs">
  <li><%= link_to "Dashboard", dashboard_path(@user), class: "nav-link", data: {"turbo-frame": :"tab_content"} %></li>
  <li><%= link_to "Calendar", calendar_path(@user), class: "nav-link", data: {"turbo-frame": :"tab_content"} %></li>
</ul>

     # tab_content turbo frame that loads the dashboard initially
<%= turbo_frame_tag "tab_content", src: dashboard_path(@user) %>

dashboard.html.erb

<%= turbo_frame_tag "tab_content" do %>
  Dashboard code...
<% end %>

calendar.html.erb

<%= turbo_frame_tag "tab_content" do %>
  Calendar code...
<% end %>

users_controller.rb

def dashboard
  respond_to do |format|
    format.html
  end
end

def calendar
  respond_to do |format|
    format.html
  end
end

This allows the turbo_frame to be replaced with the frame on the corresponding dashboard and calendar pages. And also allows the page to be directly visitable if JS is not on for example. So visiting users/1/calendar will actually load the calendar page content on screen.

Hope this helps anyone looking to do something similar. If anyone sees a better way of doing things, let me know.

4 Likes

I thought you didn’t want you put the turbo_frame_tag “tab_content” on dashboard/calendar files

No, I didn’t want to repeat putting the tab navigation links on the dashboard/calendar files.
The turbo_frame_tag “tab_content” has to wrap the content of the dashboard/calendar files in order for turbo to replace the frame tag in my show.html.web

1 Like