I've been building a new Rails 8 application recently. I'm all in on View Components, and have enjoyed building it out as pure and Rails-y as possible.

I came across a (documented) gotcha around using Rails Form Builders in View Components. Here's how I got the setup I want.

Setting default Form Builder in Rails View Components

class ApplicationComponent < ViewComponent::Base alias_method :original_form_with, :form_with def form_with(**args, &block) original_form_with(**args, builder: MyFormBuilder, &block) end end

The above renames the form_with method to original_form_with to get it out of our way. It then inserts an extra builder: MyFormBuilder, so you never have to think about it again.

Using View Components in Form Builders

For posterity, here's the rest of my Rails View Component Form set up:

class MyFormBuilder < ActionView::Helpers::FormBuilder def my_submit(**args, &block) defaults = { type: :submit } view_context.render MyButtonComponent.new(**defaults.merge(args)) end private def view_context @view_context ||= ApplicationController.new.view_context end end

Allowing you to then use:

form_with ... do |form| form.my_submit end

Here we create a new Form Builder at config/initializers/my_form_builder.rb inheriting from the default. I've added a private method to get a controller ViewContext so we can render view components with no extra faffing about.

class ApplicationController < ActionController::Base default_form_builder MyFormBuilder ... end

Lastly we set the default builder using the handy Rails default_form_builder, these folks thought of everything.

Extra Context + Sources

This was an intentional decision from the View Components team to prevent unexpected changes to rendering behavior.

Thanks to Lucas Mendelowski for the helpful article on how to easily slot VCs into Form Builders, shown above.

Bluesky