Skip to content

Turbo Frames and Streams Implementation

This implementation provides a granular approach for Turbo functionality using Turbo Frames and Turbo Streams, allowing specific sections of pages to have Turbo functionality while keeping the rest of the page (including menus and legacy functionality) untouched.

Enabling Turbo Drive at the page level was breaking functionality across the app, particularly:

  • CRM menu panel no longer loading
  • Interference with existing form interactions
  • Breaking existing AJAX functionality
  • Affecting all elements on the page, not just the specific functionality that needed Turbo

Turbo Drive is disabled by default in client/js/crm/crm.index.js:

// Disable Turbo Drive by default - we'll use Turbo Frames and Streams for specific interactions
Turbo.session.drive = false;

Turbo functionality is enabled for specific sections via:

  1. Controller Action: Add before_action :enable_turbo_frames, only: [:index] to controllers
  2. View Helper: Use turbo_section_wrapper helper to wrap sections that need Turbo functionality
  3. HTML Attribute: The wrapper adds data-turbo="true" to the section when @turbo_frames_enabled is set
  4. JavaScript Detection: The JavaScript enables Turbo functionality only for sections with the data-turbo attribute
# Enable Turbo Frames and Streams for specific sections
def enable_turbo_frames
@turbo_frames_enabled = true
end
# Enable Turbo functionality for specific sections without affecting the entire page
def turbo_section_wrapper(id: nil, class_names: nil, &block)
turbo_attrs = {}
turbo_attrs[:id] = id if id
turbo_attrs[:class] = class_names if class_names
if @turbo_frames_enabled
turbo_attrs[:'data-turbo'] = 'true'
end
content_tag(:div, turbo_attrs, &block)
end
<%= turbo_section_wrapper(id: 'videos-turbo-section', class_names: 'videos-turbo-section') do %>
<%= render 'filter_form', q: @q %>
<%= render 'videos' %>
<% end %>
// Enable Turbo functionality for specific sections
document.addEventListener('DOMContentLoaded', () => {
const turboSections = document.querySelectorAll('[data-turbo="true"]');
turboSections.forEach(section => {
console.log('🔧 Turbo enabled for section:', section.id || section.className);
// Enable Turbo Frames within this section
const turboFrames = section.querySelectorAll('turbo-frame');
turboFrames.forEach(frame => {
console.log('🔧 Turbo Frame found:', frame.id);
});
// Enable Turbo Streams for forms within this section
const turboStreamForms = section.querySelectorAll('form[data-turbo-stream]');
turboStreamForms.forEach(form => {
console.log('🔧 Turbo Stream form found:', form.action);
});
});
});

To enable Turbo Frames for specific actions in a controller:

class MyController < CrmController
before_action :enable_turbo_frames, only: [:index, :show]
def index
# Turbo Frames will be enabled for this action
end
end

Wrap sections that need Turbo functionality:

<%= turbo_section_wrapper(id: 'my-turbo-section', class_names: 'my-turbo-section') do %>
<%= render 'my_form' %>
<%= render 'my_results' %>
<% end %>
  • VideosController - index action (with Turbo Frames for filter form and results)
  1. Granular Control: Only specific sections have Turbo functionality, leaving the rest of the page untouched
  2. Menu Compatibility: CRM menu and other page elements work normally
  3. Gradual Migration: Can be enabled on more sections as needed
  4. Debugging: Clear logging shows which sections have Turbo enabled
  5. Performance: Only necessary sections use Turbo, improving overall performance
  6. Visual Feedback: Development styling helps identify Turbo-enabled sections

To test if Turbo functionality is working on a specific section:

  1. Check browser console for ”🔧 Turbo enabled for section” messages
  2. Verify the section has data-turbo="true" attribute
  3. Look for the blue dashed border around Turbo-enabled sections (development only)
  4. Test form submissions and navigation within the Turbo-enabled section
  5. Verify that the menu and other page elements work normally
  • Monitor performance impact on enabled sections
  • Consider enabling on more sections as needed
  • May need to add more Turbo Stream support for complex forms
  • Consider adding Turbo Frame support for specific components
  • Remove development styling in production
  • Add more granular control options for different types of Turbo functionality