Yield translation to `FormBuilder#button` block

When translating a `<button>` element's contents, it is tedious  to make
the translation text available to a block scope.

For instance, when rendering a `<button type="submit">` with an SVG
element as its child, passing translated label text to that SVG
element's [`<title>`][svg-title] element requires an extra call to
`I18n.translate`.

Prior to this commit, doing so would require a double lookup of the
translation key:

```erb
<%# one time here, implicitly %>
<%= form.button do %>
  <svg>
    <title>
      <!-- one time here, explicitly -->
      <%= translate("helpers.submit.post.create") %>
    </title>
    <!-- ... -->
  </svg>
<% end %>
```

This commit modifies the `ActionView::Helpers::FormBuilder#button` to
check for invocations that are passed a block, and conditionally yield
the contents of `submit_default_value` as the argument.

The new view code might look something like this:

```erb
<%= form.button do |text| %>
  <svg>
    <title><%= text %></title>
    <!-- ... -->
  </svg>
<% end %>
```

Callers of the helper are still free to omit the block parameter.

[svg-title]: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title
This commit is contained in:
Sean Doyle 2020-02-22 02:14:42 -05:00
parent 15d1d82447
commit a086418283
3 changed files with 31 additions and 4 deletions

View File

@ -1,3 +1,8 @@
* Yield translated strings to calls of `ActionView::FormBuilder#button`
when a block is given.
*Sean Doyle*
* Alias `ActionView::Helpers::Tags::Label::LabelBuilder#translation` to
`#to_s` so that `form.label` calls can yield that value to their blocks.

View File

@ -2496,10 +2496,22 @@ module ActionView
# # <strong>Ask me!</strong>
# # </button>
#
# button do |text|
# content_tag(:strong, text)
# end
# # => <button name='button' type='submit'>
# # <strong>Create post</strong>
# # </button>
#
def button(value = nil, options = {}, &block)
value, options = nil, value if value.is_a?(Hash)
value ||= submit_default_value
@template.button_tag(value, options, &block)
if block_given?
value = @template.capture { yield(value) }
end
@template.button_tag(value, options)
end
def emitted_hidden_id? # :nodoc:

View File

@ -365,6 +365,18 @@ class FormWithActsLikeFormForTest < FormWithTest
assert_dom_equal expected, output_buffer
end
def test_form_with_button_yields_translation
form_with(model: @post) do |f|
concat(f.button { |value| concat content_tag(:span, value) })
end
expected = whole_form("/posts/123", method: :patch) do
"<button name='button' type='submit'><span>Update Post</span></button>"
end
assert_dom_equal expected, output_buffer
end
def test_form_with_not_outputting_ids
old_value = ActionView::Helpers::FormHelper.form_with_generates_ids
ActionView::Helpers::FormHelper.form_with_generates_ids = false
@ -981,9 +993,7 @@ class FormWithActsLikeFormForTest < FormWithTest
form_with(model: Post.new) do |f|
concat(
f.label(:title) do |builder|
concat tag.span(builder, {
class: ("new_record" unless builder.object.persisted?)
})
concat tag.span(builder, class: ("new_record" unless builder.object.persisted?))
end
)
end