pantographe / view_component-form

Rails FormBuilder for ViewComponent
MIT License
216 stars 16 forks source link

Override `FormTagHelper`s #81

Closed boardfish closed 3 years ago

boardfish commented 3 years ago

The gem already overrides form helper methods on the builder. However, it'd also be good to have form tag helpers like text_field_tag rendering the same kinds of components if possible.

Right now, field components don't appear to be tightly coupled to the builder. <%= render ViewComponent::Form::TextFieldComponent.new(nil, nil, 'field_name') %>, for example, works just fine. Hopefully this can continue to be the case so that this issue can be done.

There's a few ways this could be done:

The former is probably better so that different builders can be used. But in order for this to be supported, we (and folks who write whole components, rather than just inheriting from what's there) will need to be sure that the components themselves can function without a builder instance.

boardfish commented 3 years ago

I've got some time to investigate this myself, so I'll see what I can come up with in the near future.

boardfish commented 3 years ago

So as a first thing, here's the method signature for FormBuilder#initialize:

def initialize(object_name, object, template, options)

Having had a play with a manually-initialized instance, it's inherently very tied to the idea of having a model attached and, for reasons yet unknown to me, the template used for rendering itself. This means it'd be quite tough for us to pass a form builder directly.

I do have an idea that'd also mitigate some of the things I've raised over here, though. Here, we're figuring out which component to render. Maybe that duty could be delegated to an object we initialize like this:

text_field_tag :name, builder: DefaultFormBuilder.for_tags

And then text_field_tag calls text_field on that object to render a component instance.

boardfish commented 3 years ago

Cross-posting from the PR for posterity - the fields helper is actually spot on for what I'm looking for here. It lets you use a builder without a backing model if you wish.

  <%= fields builder: DefaultFormBuilder do |f| %>
    <%= f.text_field :start_time %>
    <%= f.text_field :end_time %>
    <%= f.text_field :resources, multiple: true %>
  <% end %>

I'm a little surprised I'd never heard of it in the first instance, but here we are. Nothing needs to be done to solve this :sparkles:

Spone commented 3 years ago

Thanks for investigating! Would you mind opening a PR to add this to the README? I think I'll be useful to others!