Home > Lazy loading

Lazy loading

Lazy-loaded turbo frames are very useful when fetching data asynchronously from the server.

The idea with a Lazy-loaded frame, content is loaded from src when the frame becomes visible. The loaded content replaces the existing content.

<turbo-frame id="orders" src="/orders" loading="lazy">
  Content will be replaced when the frame becomes visible and /order has been loaded.
</turbo-frame>

In our example, we first make our frame visible with a skeleton UI which is used to indicate loading status.

# products/show.html.erb

<div>
  <h3 class="text-xl font-bold"><%= @product.name %> orders</h3>
  <div class="mt-5">
    <%= turbo_frame_tag :orders, src: product_orders_path(@product), loading: :lazy do %>
      <%= render "skeleton" %>
    <% end %>
  </div>
</div>
# products/skeleton.html.erb
<div class="space-y-3">
  <% 10.times do %>
    <div class="p-3 bg-gray-100 rounded-md shadow-sm animate-pulse">
      <div class="w-24 h-3 bg-gray-500 rounded"></div>
      <div class="w-64 h-3 mt-3 bg-gray-500 rounded"></div>
    </div>
  <% end %>
</div>

When the frame becomes visible turbo will request the src path. The response to the request must match the frame id.

# product_orders/index.html.erb

<%= turbo_frame_tag :orders do %>
  <div class="space-y-3">
    <%= render partial: "product_orders/order", collection: @orders %>
  </div>
<% end %>

The product_order index page is rendered as the response which replaces the frame order content hence the product list appears.