question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Turbo frames conditional rendering

See original GitHub issue

I want to stick a form in a modal, using a link that will request the new action to render the form HTML which then gets injected into the modal and opened.

This is a pretty common pattern that I’ve implemented many times before with Rails UJS.

I am now trying to do the same thing with Turbo.

<%# index.html.erb %>

<%= link_to 'New Post', new_post_path, data: { 'turbo-frame': 'modal-body' } %>

<div class="modal" data-controller="modal">
  <%= turbo_frame_tag "modal-body", 'data-action': 'turbo:frame-render->modal#show' %>
</div>
<%# new.html.erb %>

<h1>New Post</h1>

<%= turbo_frame_tag "modal-body" do %>
  <%= form_with(model: @post) do |form| %>
    <div class="field">
      <%= form.label :title %>
      <%= form.text_field :title %>
    </div>

    <div class="actions">
      <%= form.submit %>
    </div>
  <% end %>
<% end %>

<%= link_to 'Show', @post %> |
<%= link_to 'Back', posts_path %>

So I have a pre-rendered empty modal with turbo_frame_tag in the modal body. When I click the link, the controller renders the new template which has the form wrapped in a matching turbo_frame_tag. The form gets injected into the modal and I have a stimulus controller which opens the modal on turbo:frame-render.

This works pretty well, but there seems to be a pretty big limitation - The form HTML has to be identical for both the modal, and for when I visit the new URL directly. For example, if I need a close button when in a modal, but a cancel link when visiting the page directly, this doesn’t seem possible to handle server-side.

With Rails UJS, My new controller action could respond to format.js for the modal and format.html when visiting directly, making it possible to render different HTML. As new action is a GET, this rules out format.turbo_stream which is for non-GET requests only.

Issue Analytics

  • State:closed
  • Created 2 years ago
  • Comments:6 (3 by maintainers)

github_iconTop GitHub Comments

1reaction
tleishcommented, Sep 8, 2021

I suggested this as a default in the turbo-rails gem

see: https://github.com/hotwired/turbo-rails/issues/229

0reactions
james-readingcommented, Sep 8, 2021

Thanks @tleish, variants work brilliants actually. It works without the boilerplate format.html do |variant| in the controller too, as long as the variant is set in the before action it renders the variant template if it exists.

Is there any harm to putting turbo_frame_request_variant in ApplicationController before all request?

Read more comments on GitHub >

github_iconTop Results From Across the Web

Conditional Rendering With Turbo Stream Broadcasts - Colby.so
Combining Turbo Streams and Frames to conditionally render content based on session variables like current_user.
Read more >
Conditionally display elements within a turbo frame?
I would like to show the button conditionally: I want to hide it if we are in the imbox, but i want to...
Read more >
Dynamic forms with Turbo - Thoughtbot
What we need is a mechanism that fetches content, then renders it within a fragment of the page. Refreshing content with Turbo Frames....
Read more >
A layout gotcha with Turbo Frames - Leftbrained
To drop layout rendering for Turbo Frame requests, turbo-rails adds a conditional layout to ActionController::Base.
Read more >
Digging into Turbo with Ruby on Rails 7 - Web-Crunch
Turbo Frames - decompose pages into independent contexts, ... We conditionally check the status and render appropriate button_to view ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found