1

I have a nested turbo frame

My controller is something like

def landing_page
  @variable = params[:variable].present? ? params[:variable] : "hello"
end

The view for my landing page is:

<%= turbo_frame_tag "outer" do %>
  <div><%= @variable %></div>
  <%= turbo_frame_tag "inner" do %>
    <div><%= @variable %></div>
    <%= link_to "link to same landing page", landing_page_path(variable: "World") %>
  <% end %>
<% end %>

On initial page render:

  1. there is no params[:variable], so the value of @variable is "hello"
  2. on the page itself, both variables successfully output the text of "hello"

When I click on the link:

  1. params[:variable] exists, therefore the value of @variable on the incoming turbo frame is "world"
  2. It modifies variable in the "inner" turbo_frame, but does not modify the variable in the "outer" turbo_frame.

This is actually the functionality I want (I am successfully able to modify the inner frame, but not the outer one). However, when looking at the network tab, this appears to be making a full HTML page request, even though it's only modifying the inner frame.

I would expect the network request to be something like:

<turbo-frame id="inner">
  <div>World</div>
  <a href="/rooms?variable=World">link to same landing page</a>
</turbo-frame>

instead, the network tab is showing that I'm receiving the entire html of

<html>
  <head>
  </head>
  <body>
    <turbo-frame id="outer">
      <div>World</div>
      <turbo-frame id="inner">
        <div>World</div>
        <a href="/rooms?variable=World">link to same landing page</a>
      </turbo-frame>
    </turbo-frame>
  </body>
</html>

The examples I've seen in the rails tutorial always seem to be predicated on the idea of going from one page to another page. Unfortunately, in my exact use case, I'm using a multistep form gem called wicked wizard and it doesn't seem like I can use turbostreams for this, and moving the inner frame outside of the outer frame isn't an option

APysnack
  • 73
  • 6
  • Your link is a "get" request. Then It doesn't leverage turbo-streams (though you can now force it to use turbo streams if required). But you are correct that your link is included in the "inner" turbo frame and then only this frame should be changed on the response received. Though maybe you are redirection to the root_url ? This would explain a full page is the actual response. Do you have a `landing_page.html.erb` view ? – Maxence Mar 14 '23 at 10:12

1 Answers1

0

That's how it works. The "full" page response you are seeing is response rendering in a turbo frame layout.

When you send request to your landing page url, controller renders a landing_page.html.erb template from landing_page action, where you have two turbo frames. That renders into a one big string and is sent back as a response.

On the front end, turbo parses the response and only updates the relevant frame, the rest is discarded. That's why TurboFrame is simpler to use. You don't need a partial or another response format.

The response you're thinking of is when you render a turbo_stream, but that's because you have to have a turbo_stream response and you have to specifically render <turbo-stream> tag:

render turbo_stream: turbo_stream.update("tag_id", "new content")
# which only renders a turbo-stream tag
<turbo-stream action="update" target="tag_id"><template>new content</template></turbo-stream>

Sure, you can also have a partial and render just the frame you need if you really want to. But I don't see why you wouldn't be able to use turbo stream or turbo frame or both:

<%= tag.div id: :current_step %>

<%= turbo_frame_tag "wizard" do %>
  <% case params[:step].presence || "one" %>
  <% when "one" %>
    <%= turbo_stream.update("current_step", "Step one") %>
    <%= link_to "next", landing_page_path(step: "two") %>
  <% when "two" %>
    <%= turbo_stream.update("current_step", "Step two") %>
    <%= link_to "next", landing_page_path(step: "complete") %>
  <% when "complete" %>
    <%= turbo_stream.update("current_step", "Step three") %>
    <%= link_to "next", landing_page_path %>
  <% end %>
<% end %>
Alex
  • 16,409
  • 6
  • 40
  • 56
  • Thank you for your response. In my scenario, the switch case logic is handled in a Wicked "steps" controller. Wicked has a "show" action and an "update" action. The update action never gets called during the link click, so any logic to render a turbo view would have to be inside the "show" action if I do something like render turbo_stream: turbo_stream.update("current_step", "Step One") inside the show action, it errors because there's already a "render wizard" handling all the other steps. I'm not sure how to map it to a dedicated turbo view since one action handles views for all the steps – APysnack Mar 14 '23 at 13:23
  • @APysnack `params[:id]` is where wicked wizard keeps the current step. when you call `render_wizard` it will render a template with the same name as the current step. just set up each step first, then wrap it in a frame, you don't need case logic. it's hard to tell you exactly what to do, you didn't show any code related to the wizard setup. your question wasn't so much about the wizard setup. i can only answer what you ask :) – Alex Mar 14 '23 at 14:44
  • I've marked your question as "accepted" because ultimately I was looking for an explanation as to why turboframes was behaving the way it was, but it seems like from your answer, it's behaving the way it's supposed to. The turbostream question is outside of the scope of the original question, so I created a separate question for it: https://stackoverflow.com/questions/75738451/using-turbostreams-in-wicked-wizards-show-action – APysnack Mar 14 '23 at 21:15