Add missing block arg for fields
The dynamic methods created by the form helper are missing the block param which makes it impossible to render slots in custom components.
Does this need a bit of test coverage before it can go in?
Thanks for your contribution @wooly! Yes, please add test coverage for this.
The methods do not include the block argument because our aim is to mirror Rails' helpers (see for instance radio_button)
Ah yes, I see. Perhaps there's a different way to do what I want to do, if you may have some suggestions?
I'm trying to allow the user to specify a piece of html to be rendered next to the input, like the go button in the below screenshot:
The way I was thinking to do it was to provide a slot for my text field component called append, and then use it like this:
<%= f.text_field :append_example, label: 'With append', placeholder: 'With append' do |c| %>
<% c.with_append do %>
BTN
<% end %>
<% end %>
but this isn't currently possible, since it appears that in my child the block isn't yielded so the with_append is never called. Unpolished code is below to have a squizz at.
module Gaia
class TextFieldComponent < ViewComponent::Form::TextFieldComponent
include FormHelpers
include ViewComponentsHelper
renders_one :append
def html_class
class_names('gaia-input', 'has-error': method_errors?)
end
def call
wrapper_tag do
concat label_tag
if append
concat input_with_inline(super)
else
concat super
end
if has_errors?
concat content_tag(:span, error_message, class: 'gaia-input-error')
elsif help_message.present?
concat content_tag(:span, help_message, class: 'gaia-input-help')
end
end
end
private
def input_with_inline(input)
render(Inline::Component.new(spacing: :xxsmall)) do
concat input
concat append
end
end
end
end
Can you think of a neater way? Any input greatly appreciated!
Thanks for elaborating, I understand your use case better.
My approach for this is to create another helper, such as group, that's in charge of wrapping your main field, adding a label, a hint, a prefix / suffix, etc.
That the 2. in this comment.
Let me know if it helps or if you'd like further guidance!
Thanks for the quick reply! I had seen the group, but felt it wouldn't fit my use case. The reasoning for this is that the appended HTML has the addon below and beside the input field itself.
So in the case of no append, the DOM would look something like this:
<div class="stack">
<label>Foo</label>
<input>
<help>
</div>
But in the append case, the DOM would look roughly like this:
<div class="stack">
<label>Foo</label>
<div class="inline">
<input>
<button>Some Button</button>
</div>
<help>
</div>
And I couldn't quite figure out how to replicate this behaviour with the group.
@Spone do you have any suggestions on how to test this?
I don't think I can use a shared example set since it's the base component that is rendered rather than a custom one with a slot. My plan was to add a text_field_with_slot_component here, and verify (somewhere) that it would render the slot HTML.
What do you think?