Skip to content

Instantly share code, notes, and snippets.

@jonknapp
Last active July 29, 2023 15:35
Show Gist options
  • Save jonknapp/84344349336780608e9227e23dae79a0 to your computer and use it in GitHub Desktop.
Save jonknapp/84344349336780608e9227e23dae79a0 to your computer and use it in GitHub Desktop.
Turbo modals using template variants

You can use different html for a modal version of a view with Turbo by taking advantage of view variants and the Turbo-Frame header. This allows a page (like http://localhost:3000/widgets/1) to show as a normal page OR to be loaded using Turbo on another page into a modal window.

The turbo_action: 'advance' on the link ensures the url updates to the new page.

The turbo_frame: 'modal' on the link will slot the resulting page's turbo frame content inside the #modal frame. However, since we also use the Turbo-Frame header to set our response variant, we will call the template app/views/widgets/show.html+modal.erb if it exists, otherwise falling back to app/views/widgets/show.html.erb. This allows us to customize the response for modal Turbo Frame requests if desired.

<html>
<body>
<%# app/views/layouts/application.html.erb %>
<%= yield %>
<%= turbo_frame_tag 'modal' %>
</body>
</html>
# app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
before_action :add_turbo_variant
private
def add_turbo_variant
return if request.variant.any?
logger.info "Turbo-Frame: #{request.headers['Turbo-Frame']}"
request.variant = request.headers['Turbo-Frame'].to_sym if request.headers['Turbo-Frame'].present?
end
end
<%# app/views/example.html.erb %>
<%= link_to "Show this page", widget_path, data: { turbo_action: 'advance', turbo_frame: 'modal' } %>
<%# app/views/widgets/show.html+modal.erb %>
<div class="modal-wrapper">
<div class="modal-body">
<h1>Alternative Modal Content</h1>
</div>
</div>
<%# app/views/widgets/show.html %>
<h1>Normal #show view</h1>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment