Skip to content

ViewComponent w/ turbo-frame + Controller render => Turbo frame swap does not occurΒ #2212

@gap777

Description

@gap777

Here are the details, as best I can understand them:

  1. I have a view component that contains a turbo frame.
  2. My VC uses the TF to swap out it's contents between two different modes (show and edit mode)
  3. The VC edit mode contains a form. Controller action is standard update action, redirecting 303 to the show action
  4. The controller show action renders the VC in show mode.

The intent is that the VC in edit mode would swap out via TF to the VC in show mode.

The observed behavior is that the HTML generated by #4 contains ONLY the VC rendered (no layout), and turbo JS treats the response as a turbo stream (not a turbo frame content swap), and adds the turbo frame to the DOM (as a sibling of body).

Steps to reproduce

Expected behavior

The render after redirect should include the TF layout.

Actual behavior

The render after redirect does not include any head or body tags.

Workaround

If I add content_type to the render call:

render MyVC.new,
            content_type: "text/html"

I get the TF layout (with head and body), and the TF replace occurs as expected.

Backtrace:

As you might already suspect, the problem is that when turbo JS follows the redirect after form submission, the accept header has 3 choices (#1 is turbo streams, #2 is HTML). Then, in actionview-7.2.2.1/lib/action_view/renderer/template_renderer.rb:71

def render_with_layout(view, template, path, locals)
        layout  = path && find_layout(path, locals.keys, [formats.first])

Only the first formats is used when selecting a layout.

System configuration

Rails version:
7.2.2.1

Ruby version:
3.4.1

Gem version:
3.21.0

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions