我希望能够生成以下标记:
<label for="field">Something <span class="hint">Field hint</span></label>
来自以下代码:
form_for ... do |f|
f.label :field, :hint => "Field hint"
end
到目前为止,我已经创建了一个初始化程序来存储自定义功能,重新打开ActionView :: Helpers :: FormBuilder并更改标签方法,但是我不确定实际获得跨度的最佳方法是什么标签的文字。如果我尝试将文本直接放入,那么正确地使用rails,就会逃避内容。
我非常想使用现有的标签基础架构,因为它具有所有验证错误支持。这排除了使用content_tag并自己生成它(这可行,但似乎不正确)。
答案 0 :(得分:3)
您应该创建自定义构建器并使用:builder参数将其传递给表单,而不是更改默认构建器。
class HintFormBuilder < ActionView::Helpers::FormBuilder
end
form_for @resource, :builder => HintFormBuilder do |f|
# ...
end
Hint构建器继承所有FormBuilder功能,包括验证,错误消息等。现在,您应该更改需要更改的内容以自定义行为。 这是一个非常原始的草案。
class HintFormBuilder < ActionView::Helpers::FormBuilder
(%w(label)).each do |selector|
src = <<-end_src
def #{selector}(method, options = {})
hint = options.delete(:hint)
returning(super) do |element|
# replace here the value of element with hint
# if hint != nil
# remember to use gsub! and not gsub
end
end
end_src
class_eval src, __FILE__, __LINE__
end
end
根据第一条评论编辑:
不要破解Rails内部结构总是一个好主意,因为您可能需要现在或将来使用依赖于原始行为的插件或功能。如果您不想在表单中手动附加构建器,则可以创建一个帮助程序。
def search_form_for(record_or_name_or_array,* args,&amp; proc) options = {:builder =&gt; HintFormBuilder}
form_for(record_or_name_or_array,
*(args << options),
&proc)
端
如果您想重新打开原始类,我建议创建一个新方法。此解决方案也适用于自定义帮助程序,并且具有您可以自定义它而不需要gsub的好处!响应。是的,gsub!这是常用的方法,因为在扩展原始方法时,您只能访问方法/选项和结果,没有值(由@object变量注入)。
class ActionView::Helpers::FormBuilder
def label_with_hint(method, text = nil, options = {})
hint = options.delete(:hint)
# do your own customizations...
@template.label(@object_name, method, text, objectify_options(options))
end
end
编辑:我错了,您可以将自定义文字作为参数传递,这样您就不需要gsub了!返回的字符串。我对text_field标签感到困惑。 此时,您可以使用第一个(使用/不使用自定义方法的子类),第二个(黑客内部)或第三个选项(使用自定义方法的黑客内部),并在将文本值发送到@ template.label之前拦截文本值。 / p>
另请注意,文字可以为零。如果为nil,则从方法自动生成该值。你应该知道这一点。
答案 1 :(得分:1)
这就是我要做的。
# config/initializers/[anything].rb
ActionView::Base.default_form_builder = CustomFormBuilder
# lib/custom_form_builder.rb
class CustomFormBuilder < ActionView::Helpers::FormBuilder
def label(field, text, options = {})
if options[:hint]
hint = @template.content_tag(:span, options[:hint], :class => "hint")
super(field, "#{field.to_s.humanize} #{hint}", options)
else
super
end
end
end