Prevent sending turbo request if the content is already populated

Hello,

I have a simple tabs content and in one of the tabs content is populated like this:

<%= turbo_frame_tag(:tags, loading: "lazy", src: some_path(some_param: param)) %>

So basically when you click on tab3 request is send and content is populated. If you switch tabs and come back to tab3 request is sent again even if content is already there.

So the question is: Is there a way we send request only once?

I can add data-turbo-cache: false but I want to see if there’s a better way.

1 Like

Another way might be to remove src or loading: "lazy" after HTML is loaded.

Hmmmm not really beacuse you can remove src from ‘< turbo-frame>’ element in the DOM but this file will still have src:

<%= turbo_frame_tag(:tags, loading: "lazy", src: some_path(some_param: param)) %> and when you click on a atb again it will send the request.

I was thinking maybe to unwrap content inside <turbo-frame> and remove it completely from the page.

Then I will just have content and no <turbo-frame> in the DOM but then probably some errors will occur because it will try send request and no <turbo-frame> tag presence.

Probably it is coming from how lazy is implemented. Maybe you “display: none” your tabs between clicks and Turbo intersect the tab every time you click on it.
It sounds like a safe bet.
And most devs just want their page refreshed when it is intersected.

Maybe you can add a dataset attribute “data-already-pulled=true” to your turbo frame and use an event such as " turbo:before-visit" to decide if you want to reload it. Turbo Reference Seem you can cancel the event if needed…

My understanding of the src attribute on frames is that if the currently loaded src matches the src it won’t load it again. I didn’t think this was reset by visibilty ?

1 Like

Me neither. The thing is that my tab content renders partial <%= partial: "some_partial" %> and inside that partial is this line <%= turbo_frame_tag("some_id", loading: "lazy", src: some_path(some_param: param)) %> which is requesting a content from another file and populates the <turbo-frame> with that content.

And I have five different tabs and each tab is built the same way. So when page loads first tab content is loaded and the rest are just holding empty turbo-frames which again gets populated with content once you click on a corresponding tab.

So I still didn’t find a way to fix this. Everytime a tab is clicked request is being sent replacing the same content.

I do exactly this myself though -

      .tab-pane.page-flex.scroll#updatesTabContent{role: 'tabpanel', aria_labelled_by: "updates-tab", data: { active_tabs_target: 'tabContent'} }
        = turbo_frame_tag :updates, src: updates_switch_path(@switch), class: "flex justify-content-center", loading: :lazy do
          = icon :spinner, class: 'spin cw align-self-center lg'

My view simply includes the turbo frame -

= turbo_frame_tag :updates do

Turbo picks the content out of the response and injects it into the frame, and then stores the path in src on the dom element (not the src attribute)
It never loads it again - I have a double click action on the tab to allow refresh.

How and what are you rendering on your lazy load path ?

Basically it’s just calling this file:

<%= turbo_frame_tag(:tags) do %>
  <div id="tags-management">
    <header>
      <p class="lead"><%= t("tags.index.heading") %></p>
    </header>
    <div class="search-area">
      <%= render("agendas/tags/index/filter", filter_params: filter_params) %>
    </div>
    <div id="folder-tags">
      <div class="tags-header">
        <div class="name"><%= t("tags.table.header.tag_name") %></div>
        <div class="updated"><%= t("tags.table.header.last_updated") %></div>
        <div class="actions"></div>
      </div>
      <div class="tags-content">
        <% if @tags.any? %>
          <%= render(partial: "agendas/tags/index/tag_preview", collection: @tags, as: :tag) %>
        <% else %>
          <div class="no-tags">
            <%= render partial: "agendas/tags/index/blank_slate", locals: { rows: 6, columns: 3, max_item_width: 40, label: "No Data" } %>
          </div>
        <% end %>
      </div>
    </div>
    <%= render("application/pagination", presenter: OpenStruct.new(pagy: @pagy)) %>
  </div>
<% end %>

And this is before clicking on a tab, it’s just empty turbo-frame:

and after clicking on a tab: