Known issues

Issues resolved by the optional capture compatibility patch

If you’re experiencing issues with duplicated content or malformed HTML output, the capture compatibility patch may resolve these.

Set config.view_component.capture_compatibility_patch_enabled to true to resolve these issues.

These issues arise because the related features/methods keep a reference to the primary ActionView::Base instance, which has its own @output_buffer. When #capture is called on the original ActionView::Base instance while evaluating a block from a ViewComponent, the @output_buffer is overridden in the ActionView::Base instance, and not the component. This results in a double render due to #capture implementation details.

To resolve the issue, we override #capture so that we can delegate the capture logic to the ViewComponent that created the block.

turbo_frame_tag double rendering or scrambled HTML structure

When using turbo_frame_tag inside a ViewComponent, the template may be rendered twice. See https://github.com/github/view_component/issues/1099.

As a workaround, use tag.turbo_frame instead of turbo_frame_tag.

Note: For the same functionality as turbo_frame_tag(my_model), use tag.turbo_frame(id: dom_id(my_model)).

Compatibility with Rails form helpers

ViewComponent isn’t compatible with form_for helpers by default.

Passing a form object (often f) to a ViewComponent works for simple cases like f.text_field :name. Content may be ill-ordered or duplicated in complex cases, such as passing blocks to form helpers or when nesting components.

Some workarounds include:

  • Experimental: Enable the capture compatibility patch with config.view_component.capture_compatibility_patch_enabled = true.
  • Render an entire form within a single ViewComponent.
  • Render a partial within the ViewComponent which includes the form.
  • Use a custom FormBuilder to create reusable form components:

Forms don’t use the default FormBuilder

Calls to form helpers such as form_with in ViewComponents don’t use the default form builder. This is by design, as it allows global state to change the rendered output of a component. Instead, consider passing a form builder into form helpers via the builder argument:

<%= form_for(record, builder: CustomFormBuilder) do |f| %>
  <%= f.text_field :name %>
<% end %>

Inconsistent controller rendering behavior between Rails versions

In versions of Rails < 6.1, rendering a ViewComponent from a controller doesn’t include the layout.