2009-06-21 88 views
1

我希望能够生成以下标记:在创建自定义表单标签字段

<label for="field">Something <span class="hint">Field hint</span></label> 

从下面的代码:

form_for ... do |f| 
    f.label :field, :hint => "Field hint" 
end 

到目前为止,我已经创建了一个初始化器存储其自定义的功能重新开启::的ActionView ::助手和FormBuilder改变标签的方法,但是我不知道什么是最好的方式来实际获得跨度到文本的标签。如果我尝试将文本直接放入文件夹中,则正确地如此,就会漏掉内容。

我挺想利用现有的基础设施的标签,因为它拥有所有的验证错误的支持。这排除了使用content_tag并自己生成它(这会工作,但似乎不是......)。

回答

3

除了更改默认的建设者,你应该创建一个自定义生成器,并将其传递到与形式:建设者参数。

class HintFormBuilder < ActionView::Helpers::FormBuilder 
end 

form_for @resource, :builder => HintFormBuilder do |f| 
# ... 
end 

该提示构建器继承了所有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内部,因为你可能需要使用,现在还是将来,插件或功能依赖原来的行为。如果您不想在表单中手动追加生成器,则可以创建一个帮助器。

高清search_form_for(record_or_name_or_array,* ARGS,& PROC) 选项= {:建设者=> 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。

另请注意,文本可以为零。如果为零,则该值是从方法自动生成的。你应该知道这一点。

+0

我真的不希望有指定表单生成器我想每个表单上使用。此外,我敢肯定,必须有比gsub-ing的价值更好的方式... – jonnii 2009-06-22 00:02:27

+0

我不知道为什么有人投这个帖子。 – jonnii 2009-06-24 13:55:03

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